@@ -320,17 +320,43 @@ transfer:
320320``` python
321321from irods.parallel import abort_parallel_transfers
322322
323- def handler (* arguments ):
323+ def handler (signal , _ )
324324 abort_parallel_transfers()
325+ os._exit(128 + signal)
325326
326- signal(SIGINT ,handler)
327+ signal(SIGTERM ,handler)
327328
328329try :
329330 # a multi-1247 put or get can leave non-daemon threads running if not treated with care.
330331 session.data_objects.put( ... )
331332except KeyboardInterrupt :
332333 abort_parallel_transfers()
333- ```
334+ printf(' Due to a SIGINT or Control-C, the put failed.' )
335+ # Raise again if we wish to exit the application.
336+ raise
337+ except RuntimeError :
338+ printf(' The put failed.' )
339+ # ...
340+ ```
341+
342+ Note that if had we intercepted SIGINT by assigning it, also, a non-default
343+ handler, we would have avoided the need to handle the ` KeyboardInterrupt `
344+ inline.
345+
346+ (Internally, of course, the PRC must handle all eventualities, including
347+ ` KeyboardInterrupt ` , by closing down the current foreground transfer.
348+ Otherwise we would risk some non-daemon threads not finishing, and this
349+ potentially risks holding
350+ up the main program from eventually performing an orderly exit.)
351+
352+ If a signal handler calls abort_parallel_transfers() but does not call
353+ ` os._exit ` after doing so, a parallel ` put ` or ` get ` can raise a ` RuntimeError `
354+ to indicate the failed transfer.
355+
356+ In general it is better (for simpler applications wanting to gracefully handle
357+ interrupted lengthy data transfers to/from iRODS data objects) to anticipate
358+ control-C by handling both ` KeyboardInterrupt ` and ` RuntimeError ` , as shown
359+ above.
334360
335361Progress bars
336362-------------
0 commit comments