@@ -150,6 +150,8 @@ def __init__(self,
150
150
level : int = isal_zlib .ISAL_DEFAULT_COMPRESSION ,
151
151
threads : int = 1 ,
152
152
queue_size : int = 2 ):
153
+ self .lock = threading .Lock ()
154
+ self .exception = None
153
155
self .raw = fp
154
156
self .level = level
155
157
self .previous_block = b""
@@ -189,14 +191,17 @@ def start(self):
189
191
for worker in self .compression_workers :
190
192
worker .start ()
191
193
192
- def stop_immediately (self ):
194
+ def stop (self ):
193
195
"""Stop, but do not care for remaining work"""
194
196
self .running = False
195
- self .output_worker .join ()
196
197
for worker in self .compression_workers :
197
198
worker .join ()
199
+ self .output_worker .join ()
198
200
199
201
def write (self , b ) -> int :
202
+ with self .lock :
203
+ if self .exception :
204
+ raise self .exception
200
205
if self ._closed :
201
206
raise IOError ("Can not write closed file" )
202
207
index = self .index
@@ -221,7 +226,9 @@ def flush(self):
221
226
222
227
def close (self ) -> None :
223
228
self .flush ()
224
- self .stop_immediately ()
229
+ self .stop ()
230
+ if self .exception :
231
+ raise self .exception
225
232
# Write an empty deflate block with a lost block marker.
226
233
self .raw .write (isal_zlib .compress (b"" , wbits = - 15 ))
227
234
trailer = struct .pack ("<II" , self ._crc , self ._size & 0xFFFFFFFF )
@@ -237,16 +244,31 @@ def closed(self) -> bool:
237
244
def _compress (self , index : int ):
238
245
in_queue = self .input_queues [index ]
239
246
out_queue = self .output_queues [index ]
240
- while self . running :
247
+ while True :
241
248
try :
242
249
data , zdict = in_queue .get (timeout = 0.05 )
243
250
except queue .Empty :
251
+ if not self .running :
252
+ return
244
253
continue
245
- compressor = isal_zlib .compressobj (
246
- self .level , wbits = - 15 , zdict = zdict )
247
- compressed = compressor .compress (data ) + compressor .flush (
248
- isal_zlib .Z_SYNC_FLUSH )
249
- crc = isal_zlib .crc32 (data )
254
+ try :
255
+ compressor = isal_zlib .compressobj (
256
+ self .level , wbits = - 15 , zdict = zdict )
257
+ compressed = compressor .compress (data ) + compressor .flush (
258
+ isal_zlib .Z_SYNC_FLUSH )
259
+ crc = isal_zlib .crc32 (data )
260
+ except Exception as e :
261
+ with self .lock :
262
+ self .exception = e
263
+ # Abort everything and empty the queue
264
+ in_queue .task_done ()
265
+ self .running = False
266
+ while True :
267
+ try :
268
+ _ = in_queue .get (timeout = 0.05 )
269
+ in_queue .task_done ()
270
+ except queue .Empty :
271
+ return
250
272
data_length = len (data )
251
273
out_queue .put ((compressed , crc , data_length ))
252
274
in_queue .task_done ()
@@ -257,20 +279,22 @@ def _write(self):
257
279
fp = self .raw
258
280
total_crc = 0
259
281
size = 0
260
- while self . running :
282
+ while True :
261
283
out_index = index % self .threads
262
284
output_queue = output_queues [out_index ]
263
285
try :
264
286
compressed , crc , data_length = output_queue .get (timeout = 0.05 )
265
287
except queue .Empty :
288
+ if not self .running :
289
+ self ._crc = total_crc
290
+ self ._size = size
291
+ return
266
292
continue
267
293
total_crc = isal_zlib .crc32_combine (total_crc , crc , data_length )
268
294
size += data_length
269
295
fp .write (compressed )
270
296
output_queue .task_done ()
271
297
index += 1
272
- self ._crc = total_crc
273
- self ._size = size
274
298
275
299
def writable (self ) -> bool :
276
300
return True
0 commit comments