@@ -438,6 +438,12 @@ def __init__(self, _init_logging=True):
438438 :param bool _init_logging:
439439 For testing, if :data:`False`, don't initialize logging.
440440 """
441+ # #573: The process ID that installed the :mod:`atexit` handler. If
442+ # some unknown Ansible plug-in forks the Ansible top-level process and
443+ # later performs a graceful Python exit, it may try to wait for child
444+ # PIDs it never owned, causing a crash. We want to avoid that.
445+ self ._pid = os .getpid ()
446+
441447 common_setup (_init_logging = _init_logging )
442448
443449 self .parent_sock , self .child_sock = socket .socketpair ()
@@ -451,7 +457,7 @@ def __init__(self, _init_logging=True):
451457 for mux in self ._muxes :
452458 mux .start ()
453459
454- atexit .register (self ._on_process_exit , self . parent_sock )
460+ atexit .register (self ._on_process_exit )
455461 self .child_sock .close ()
456462 self .child_sock = None
457463
@@ -487,7 +493,7 @@ def _reconnect(self, path):
487493
488494 self .listener_path = path
489495
490- def _on_process_exit (self , sock ):
496+ def _on_process_exit (self ):
491497 """
492498 This is an :mod:`atexit` handler installed in the top-level process.
493499
@@ -501,15 +507,18 @@ def _on_process_exit(self, sock):
501507 MuxProcess, debug logs may appear on the user's terminal *after* the
502508 prompt has been printed.
503509 """
510+ if self ._pid != os .getpid ():
511+ return
512+
504513 try :
505- sock .shutdown (socket .SHUT_WR )
514+ self . parent_sock .shutdown (socket .SHUT_WR )
506515 except socket .error :
507516 # Already closed. This is possible when tests are running.
508517 LOG .debug ('_on_process_exit: ignoring duplicate call' )
509518 return
510519
511- mitogen .core .io_op (sock .recv , 1 )
512- sock .close ()
520+ mitogen .core .io_op (self . parent_sock .recv , 1 )
521+ self . parent_sock .close ()
513522
514523 for mux in self ._muxes :
515524 _ , status = os .waitpid (mux .pid , 0 )
0 commit comments