@@ -908,6 +908,19 @@ def _done_callback(fut, cur_task=cur_task):
908908 return outer
909909
910910
911+ def _log_on_cancel_callback (inner ):
912+ if not inner .cancelled ():
913+ exc = inner .exception ()
914+ context = {
915+ 'message' :
916+ f'{ exc .__class__ .__name__ } exception in shielded future' ,
917+ 'exception' : exc ,
918+ 'future' : inner ,
919+ }
920+ if inner ._source_traceback :
921+ context ['source_traceback' ] = inner ._source_traceback
922+ inner ._loop .call_exception_handler (context )
923+
911924def shield (arg ):
912925 """Wait for a future, shielding it from cancellation.
913926
@@ -953,14 +966,11 @@ def shield(arg):
953966 else :
954967 cur_task = None
955968
956- def _inner_done_callback (inner , cur_task = cur_task ):
957- if cur_task is not None :
958- futures .future_discard_from_awaited_by (inner , cur_task )
969+ def _clear_awaited_by_callback (inner ):
970+ futures .future_discard_from_awaited_by (inner , cur_task )
959971
972+ def _inner_done_callback (inner ):
960973 if outer .cancelled ():
961- if not inner .cancelled ():
962- # Mark inner's result as retrieved.
963- inner .exception ()
964974 return
965975
966976 if inner .cancelled ():
@@ -972,10 +982,16 @@ def _inner_done_callback(inner, cur_task=cur_task):
972982 else :
973983 outer .set_result (inner .result ())
974984
975-
976985 def _outer_done_callback (outer ):
977986 if not inner .done ():
978987 inner .remove_done_callback (_inner_done_callback )
988+ # Keep only one callback to log on cancel
989+ inner .remove_done_callback (_log_on_cancel_callback )
990+ inner .add_done_callback (_log_on_cancel_callback )
991+
992+ if cur_task is not None :
993+ inner .add_done_callback (_clear_awaited_by_callback )
994+
979995
980996 inner .add_done_callback (_inner_done_callback )
981997 outer .add_done_callback (_outer_done_callback )
0 commit comments