@@ -114,14 +114,17 @@ def get_worker_model():
114114 return _worker_model
115115
116116
117- def get_classic_worker_model ():
117+ def get_classic_worker_model (** kwargs ):
118118 """
119119 Return the single :class:`ClassicWorkerModel` instance, constructing it if
120120 necessary.
121121 """
122122 global _classic_worker_model
123+ assert _classic_worker_model is None or (not kwargs ), \
124+ "ClassicWorkerModel kwargs supplied but model already constructed"
125+
123126 if _classic_worker_model is None :
124- _classic_worker_model = ClassicWorkerModel ()
127+ _classic_worker_model = ClassicWorkerModel (** kwargs )
125128 return _classic_worker_model
126129
127130
@@ -417,9 +420,9 @@ def _initialize(self):
417420 For testing, if :data:`False`, don't initialize logging.
418421 """
419422 common_setup (_init_logging = self ._init_logging )
423+
420424 MuxProcess .cls_parent_sock , \
421425 MuxProcess .cls_child_sock = socket .socketpair ()
422-
423426 mitogen .core .set_cloexec (MuxProcess .cls_parent_sock .fileno ())
424427 mitogen .core .set_cloexec (MuxProcess .cls_child_sock .fileno ())
425428
@@ -434,6 +437,28 @@ def _initialize(self):
434437 MuxProcess .cls_child_sock .close ()
435438 MuxProcess .cls_child_sock = None
436439
440+ def _test_reset (self ):
441+ """
442+ Used to clean up in unit tests.
443+ """
444+ # TODO: split this up a bit.
445+ global _classic_worker_model
446+ assert MuxProcess .cls_parent_sock is not None
447+ MuxProcess .cls_parent_sock .close ()
448+ MuxProcess .cls_parent_sock = None
449+ self .listener_path = None
450+ self .router = None
451+ self .parent = None
452+
453+ for mux in self ._muxes :
454+ pid , status = os .waitpid (mux .pid , 0 )
455+ status = mitogen .fork ._convert_exit_status (status )
456+ LOG .debug ('mux PID %d %s' , pid ,
457+ mitogen .parent .returncode_to_str (status ))
458+
459+ _classic_worker_model = None
460+ set_worker_model (None )
461+
437462 def on_strategy_start (self ):
438463 """
439464 See WorkerModel.on_strategy_start().
@@ -461,22 +486,26 @@ def get_binding(self, inventory_name):
461486 return ClassicBinding (self )
462487
463488 def on_binding_close (self ):
464- if self .broker :
465- self .broker .shutdown ()
466- self .broker .join ()
467- self .router = None
468- self .broker = None
489+ if not self .broker :
490+ return
491+
492+ self .broker .shutdown ()
493+ self .broker .join ()
494+ self .router = None
495+ self .broker = None
496+ self .listener_path = None
497+ self .initialized = False
469498
470- # #420: Ansible executes "meta" actions in the top-level process,
471- # meaning "reset_connection" will cause :class:`mitogen.core.Latch`
472- # FDs to be cached and erroneously shared by children on subsequent
473- # WorkerProcess forks. To handle that, call on_fork() to ensure any
474- # shared state is discarded.
475- # #490: only attempt to clean up when it's known that some
476- # resources exist to cleanup, otherwise later __del__ double-call
477- # to close() due to GC at random moment may obliterate an unrelated
478- # Connection's related resources.
479- mitogen .fork .on_fork ()
499+ # #420: Ansible executes "meta" actions in the top-level process,
500+ # meaning "reset_connection" will cause :class:`mitogen.core.Latch` FDs
501+ # to be cached and erroneously shared by children on subsequent
502+ # WorkerProcess forks. To handle that, call on_fork() to ensure any
503+ # shared state is discarded.
504+ # #490: only attempt to clean up when it's known that some resources
505+ # exist to cleanup, otherwise later __del__ double-call to close() due
506+ # to GC at random moment may obliterate an unrelated Connection's
507+ # related resources.
508+ mitogen .fork .on_fork ()
480509
481510
482511class MuxProcess (object ):
@@ -514,28 +543,14 @@ class of problems this worker is intended to avoid.
514543 #: applied to locally executed commands and modules.
515544 cls_original_env = None
516545
517- #: In both processes, this a list of the temporary UNIX sockets used for
518- #: forked WorkerProcesses to contact the forked mux processes.
519- cls_listener_paths = None
520-
521- @classmethod
522- def _reset (cls ):
523- """
524- Used to clean up in unit tests.
525- """
526- assert cls .worker_sock is not None
527- cls .worker_sock .close ()
528- cls .worker_sock = None
529- os .waitpid (cls .worker_pid , 0 )
530-
531546 def __init__ (self , index ):
532547 self .index = index
533548 #: Individual path of this process.
534549 self .path = mitogen .unix .make_socket_path ()
535550
536551 def start (self ):
537- pid = os .fork ()
538- if pid :
552+ self . pid = os .fork ()
553+ if self . pid :
539554 # Wait for child to boot before continuing.
540555 mitogen .core .io_op (MuxProcess .cls_parent_sock .recv , 1 )
541556 return
0 commit comments