@@ -62,18 +62,6 @@ def test_basic_get_set(self) -> None:
6262 v .set (99 )
6363 assert v .get () == 99
6464
65- def test_bool_truthy (self ) -> None :
66- v = ThreadSafeVal (True )
67- assert bool (v ) is True
68- v .set (False )
69- assert bool (v ) is False
70-
71- def test_bool_zero (self ) -> None :
72- v = ThreadSafeVal (0 )
73- assert bool (v ) is False
74- v .set (1 )
75- assert bool (v ) is True
76-
7765 def test_context_manager_returns_value (self ) -> None :
7866 v = ThreadSafeVal ("hello" )
7967 with v as val :
@@ -113,20 +101,6 @@ def do_it() -> None:
113101 t .join (timeout = 2 )
114102 assert result .is_set (), "Deadlocked! get() inside with block hung"
115103
116- def test_bool_inside_context_manager_no_deadlock (self ) -> None :
117- v = ThreadSafeVal (True )
118- result = threading .Event ()
119-
120- def do_it () -> None :
121- with v :
122- _ = bool (v )
123- result .set ()
124-
125- t = threading .Thread (target = do_it )
126- t .start ()
127- t .join (timeout = 2 )
128- assert result .is_set (), "Deadlocked! bool() inside with block hung"
129-
130104 def test_context_manager_blocks_other_threads (self ) -> None :
131105 """While one thread holds the lock via `with`, others should block on set()."""
132106 v = ThreadSafeVal (0 )
@@ -245,6 +219,7 @@ def target() -> None:
245219 ran .set ()
246220
247221 mt = ModuleThread (module = mod , target = target , name = "test-basic" )
222+ mt .start ()
248223 ran .wait (timeout = 2 )
249224 assert ran .is_set ()
250225 mt .stop ()
@@ -254,14 +229,15 @@ def test_auto_start(self) -> None:
254229 mod = FakeModule ()
255230 started = threading .Event ()
256231 mt = ModuleThread (module = mod , target = started .set , name = "test-autostart" )
232+ mt .start ()
257233 started .wait (timeout = 2 )
258234 assert started .is_set ()
259235 mt .stop ()
260236
261237 def test_deferred_start (self ) -> None :
262238 mod = FakeModule ()
263239 started = threading .Event ()
264- mt = ModuleThread (module = mod , target = started .set , name = "test-deferred" , start = False )
240+ mt = ModuleThread (module = mod , target = started .set , name = "test-deferred" )
265241 time .sleep (0.1 )
266242 assert not started .is_set ()
267243 mt .start ()
@@ -275,11 +251,11 @@ def test_stopping_property(self) -> None:
275251 holder : list [ModuleThread ] = []
276252
277253 def target () -> None :
278- while not holder [0 ].stopping :
254+ while holder [0 ].status . get () == "running" :
279255 time .sleep (0.01 )
280256 saw_stopping .set ()
281257
282- mt = ModuleThread (module = mod , target = target , name = "test-stopping" , start = False )
258+ mt = ModuleThread (module = mod , target = target , name = "test-stopping" )
283259 holder .append (mt )
284260 mt .start ()
285261 time .sleep (0.05 )
@@ -290,6 +266,7 @@ def target() -> None:
290266 def test_stop_idempotent (self ) -> None :
291267 mod = FakeModule ()
292268 mt = ModuleThread (module = mod , target = lambda : time .sleep (0.01 ), name = "test-idem" )
269+ mt .start ()
293270 time .sleep (0.05 )
294271 mt .stop ()
295272 mt .stop () # second call should not raise
@@ -305,7 +282,7 @@ def target() -> None:
305282 holder [0 ].stop () # stop ourselves — should not deadlock
306283 result .set ()
307284
308- mt = ModuleThread (module = mod , target = target , name = "test-self-stop" , start = False )
285+ mt = ModuleThread (module = mod , target = target , name = "test-self-stop" )
309286 holder .append (mt )
310287 mt .start ()
311288 result .wait (timeout = 3 )
@@ -319,10 +296,10 @@ def test_dispose_stops_thread(self) -> None:
319296
320297 def target () -> None :
321298 running .set ()
322- while not holder [0 ].stopping :
299+ while holder [0 ].status . get () == "running" :
323300 time .sleep (0.01 )
324301
325- mt = ModuleThread (module = mod , target = target , name = "test-dispose" , start = False )
302+ mt = ModuleThread (module = mod , target = target , name = "test-dispose" )
326303 holder .append (mt )
327304 mt .start ()
328305 running .wait (timeout = 2 )
@@ -336,10 +313,10 @@ def test_concurrent_stop_calls(self) -> None:
336313 holder : list [ModuleThread ] = []
337314
338315 def target () -> None :
339- while not holder [0 ].stopping :
316+ while holder [0 ].status . get () == "running" :
340317 time .sleep (0.01 )
341318
342- mt = ModuleThread (module = mod , target = target , name = "test-concurrent-stop" , start = False )
319+ mt = ModuleThread (module = mod , target = target , name = "test-concurrent-stop" )
343320 holder .append (mt )
344321 mt .start ()
345322 time .sleep (0.05 )
@@ -369,6 +346,7 @@ def stubborn_target() -> None:
369346 mt = ModuleThread (
370347 module = mod , target = stubborn_target , name = "test-timeout" , close_timeout = 0.2
371348 )
349+ mt .start ()
372350 start = time .monotonic ()
373351 mt .stop ()
374352 elapsed = time .monotonic () - start
@@ -381,10 +359,10 @@ def test_stop_concurrent_with_dispose(self) -> None:
381359 holder : list [ModuleThread ] = []
382360
383361 def target (h : list [ModuleThread ] = holder ) -> None :
384- while not h [0 ].stopping :
362+ while h [0 ].status . get () == "running" :
385363 time .sleep (0.001 )
386364
387- mt = ModuleThread (module = mod , target = target , name = "test-stop-dispose" , start = False )
365+ mt = ModuleThread (module = mod , target = target , name = "test-stop-dispose" )
388366 holder .append (mt )
389367 mt .start ()
390368 time .sleep (0.02 )
@@ -490,6 +468,7 @@ def test_basic_lifecycle(self) -> None:
490468 args = [PYTHON , "-c" , "import time; time.sleep(30)" ],
491469 shutdown_timeout = 2.0 ,
492470 )
471+ mp .start ()
493472 assert mp .is_alive
494473 assert mp .pid is not None
495474 mp .stop ()
@@ -503,6 +482,7 @@ def test_stop_idempotent(self) -> None:
503482 args = [PYTHON , "-c" , "import time; time.sleep(30)" ],
504483 shutdown_timeout = 1.0 ,
505484 )
485+ mp .start ()
506486 mp .stop ()
507487 mp .stop () # should not raise
508488 mp .stop ()
@@ -514,6 +494,7 @@ def test_dispose_stops_process(self) -> None:
514494 args = [PYTHON , "-c" , "import time; time.sleep(30)" ],
515495 shutdown_timeout = 2.0 ,
516496 )
497+ mp .start ()
517498 mod .dispose ()
518499 time .sleep (0.5 )
519500 assert not mp .is_alive
@@ -523,23 +504,25 @@ def test_on_exit_fires_on_natural_exit(self) -> None:
523504 mod = FakeModule ()
524505 exit_called = threading .Event ()
525506
526- ModuleProcess (
507+ mp = ModuleProcess (
527508 module = mod ,
528509 args = [PYTHON , "-c" , "print('done')" ],
529510 on_exit = exit_called .set ,
530511 )
512+ mp .start ()
531513 exit_called .wait (timeout = 5 )
532514 assert exit_called .is_set (), "on_exit was not called after natural process exit"
533515
534516 def test_on_exit_fires_on_crash (self ) -> None :
535517 mod = FakeModule ()
536518 exit_called = threading .Event ()
537519
538- ModuleProcess (
520+ mp = ModuleProcess (
539521 module = mod ,
540522 args = [PYTHON , "-c" , "import sys; sys.exit(1)" ],
541523 on_exit = exit_called .set ,
542524 )
525+ mp .start ()
543526 exit_called .wait (timeout = 5 )
544527 assert exit_called .is_set (), "on_exit was not called after process crash"
545528
@@ -554,6 +537,7 @@ def test_on_exit_not_fired_on_stop(self) -> None:
554537 on_exit = exit_called .set ,
555538 shutdown_timeout = 2.0 ,
556539 )
540+ mp .start ()
557541 time .sleep (0.2 ) # let watchdog start
558542 mp .stop ()
559543 time .sleep (1.0 ) # give watchdog time to potentially fire
@@ -565,6 +549,7 @@ def test_stdout_logged(self) -> None:
565549 module = mod ,
566550 args = [PYTHON , "-c" , "print('hello from subprocess')" ],
567551 )
552+ mp .start ()
568553 time .sleep (1.0 ) # let output be read
569554 mp .stop ()
570555
@@ -574,6 +559,7 @@ def test_stderr_logged(self) -> None:
574559 module = mod ,
575560 args = [PYTHON , "-c" , "import sys; sys.stderr.write('error msg\\ n')" ],
576561 )
562+ mp .start ()
577563 time .sleep (1.0 )
578564 mp .stop ()
579565
@@ -588,6 +574,7 @@ def test_log_json_mode(self) -> None:
588574 ],
589575 log_json = True ,
590576 )
577+ mp .start ()
591578 time .sleep (1.0 )
592579 mp .stop ()
593580
@@ -598,6 +585,7 @@ def test_log_json_malformed(self) -> None:
598585 args = [PYTHON , "-c" , "print('not json')" ],
599586 log_json = True ,
600587 )
588+ mp .start ()
601589 time .sleep (1.0 )
602590 mp .stop ()
603591
@@ -614,6 +602,7 @@ def test_stop_process_that_ignores_sigterm(self) -> None:
614602 shutdown_timeout = 0.5 ,
615603 kill_timeout = 2.0 ,
616604 )
605+ mp .start ()
617606 time .sleep (0.2 )
618607 start = time .monotonic ()
619608 mp .stop ()
@@ -629,6 +618,7 @@ def test_stop_already_dead_process(self) -> None:
629618 module = mod ,
630619 args = [PYTHON , "-c" , "pass" ], # exits immediately
631620 )
621+ mp .start ()
632622 time .sleep (1.0 ) # let it die
633623 mp .stop () # should not raise
634624
@@ -639,6 +629,7 @@ def test_concurrent_stop(self) -> None:
639629 args = [PYTHON , "-c" , "import time; time.sleep(30)" ],
640630 shutdown_timeout = 2.0 ,
641631 )
632+ mp .start ()
642633 errors = []
643634
644635 def stop_it () -> None :
@@ -667,11 +658,12 @@ def fake_module_stop() -> None:
667658 mod .dispose ()
668659 stop_called .set ()
669660
670- ModuleProcess (
661+ mp = ModuleProcess (
671662 module = mod ,
672663 args = [PYTHON , "-c" , "pass" ], # exits immediately
673664 on_exit = fake_module_stop ,
674665 )
666+ mp .start ()
675667 stop_called .wait (timeout = 5 )
676668 assert stop_called .is_set (), "Deadlocked! on_exit -> dispose -> stop chain hung"
677669
@@ -685,7 +677,6 @@ def test_deferred_start(self) -> None:
685677 mp = ModuleProcess (
686678 module = mod ,
687679 args = [PYTHON , "-c" , "import time; time.sleep(30)" ],
688- start = False ,
689680 )
690681 assert not mp .is_alive
691682 mp .start ()
@@ -696,7 +687,7 @@ def test_env_passed(self) -> None:
696687 mod = FakeModule ()
697688 exit_called = threading .Event ()
698689
699- ModuleProcess (
690+ mp = ModuleProcess (
700691 module = mod ,
701692 args = [
702693 PYTHON ,
@@ -706,6 +697,7 @@ def test_env_passed(self) -> None:
706697 env = {** os .environ , "MY_VAR" : "42" },
707698 on_exit = exit_called .set ,
708699 )
700+ mp .start ()
709701 exit_called .wait (timeout = 5 )
710702 # Process should have exited with 0 (our on_exit fires for all unmanaged exits)
711703 assert exit_called .is_set ()
@@ -717,6 +709,7 @@ def test_cwd_passed(self) -> None:
717709 args = [PYTHON , "-c" , "import os; print(os.getcwd())" ],
718710 cwd = "/tmp" ,
719711 )
712+ mp .start ()
720713 time .sleep (1.0 )
721714 mp .stop ()
722715
@@ -826,23 +819,25 @@ def test_chain_no_deadlock_fast_exit(self) -> None:
826819 for _ in range (20 ):
827820 mod = FakeModule ()
828821 done = threading .Event ()
829- ModuleProcess (
822+ mp = ModuleProcess (
830823 module = mod ,
831824 args = [PYTHON , "-c" , "pass" ],
832825 on_exit = self ._make_fake_stop (mod , done ),
833826 )
827+ mp .start ()
834828 assert done .wait (timeout = 5 ), "Deadlock in dispose chain (fast exit)"
835829
836830 def test_chain_no_deadlock_slow_exit (self ) -> None :
837831 """Process runs briefly then exits."""
838832 for _ in range (10 ):
839833 mod = FakeModule ()
840834 done = threading .Event ()
841- ModuleProcess (
835+ mp = ModuleProcess (
842836 module = mod ,
843837 args = [PYTHON , "-c" , "import time; time.sleep(0.1)" ],
844838 on_exit = self ._make_fake_stop (mod , done ),
845839 )
840+ mp .start ()
846841 assert done .wait (timeout = 5 ), "Deadlock in dispose chain (slow exit)"
847842
848843 def test_chain_concurrent_with_external_stop (self ) -> None :
@@ -856,6 +851,7 @@ def test_chain_concurrent_with_external_stop(self) -> None:
856851 on_exit = self ._make_fake_stop (mod , done ),
857852 shutdown_timeout = 1.0 ,
858853 )
854+ mp .start ()
859855 # Race: the process might exit naturally or we might stop it
860856 time .sleep (0.03 )
861857 mp .stop ()
@@ -874,11 +870,12 @@ def slow_stop(self_mt: ModuleThread) -> None:
874870 mod = FakeModule ()
875871 done = threading .Event ()
876872 with mock .patch .object (ModuleThread , "stop" , slow_stop ):
877- ModuleProcess (
873+ mp = ModuleProcess (
878874 module = mod ,
879875 args = [PYTHON , "-c" , "pass" ],
880876 on_exit = self ._make_fake_stop (mod , done ),
881877 )
878+ mp .start ()
882879 assert done .wait (timeout = 10 ), "Deadlock with slow ModuleThread.stop()"
883880
884881
0 commit comments