@@ -50,8 +50,7 @@ def with_running_supervisor(supervisor: Multiprocess):
5050 # Signal supervisor to exit (in case test failed before sending SIGINT)
5151 supervisor .should_exit .set ()
5252 thread .join (timeout = 10 )
53- if thread .is_alive ():
54- raise RuntimeError ("Supervisor thread did not exit in time" )
53+ assert not thread .is_alive ()
5554
5655
5756async def app (scope : Scope , receive : ASGIReceiveCallable , send : ASGISendCallable ) -> None :
@@ -94,6 +93,54 @@ def test_process_is_alive_when_not_started() -> None:
9493 assert not process .is_alive (timeout = 0.1 )
9594
9695
96+ @new_console_in_windows
97+ def test_process_always_pong_exits_on_closed_socket () -> None :
98+ """Test that always_pong exits gracefully when the peer socket is closed."""
99+ process = Process (Config (app = app ), target = lambda x : None , sockets = [])
100+ thread = threading .Thread (target = process .always_pong , daemon = True )
101+ thread .start ()
102+ process .parent_sock .close ()
103+ thread .join (timeout = 2 )
104+ assert not thread .is_alive ()
105+
106+
107+ @new_console_in_windows
108+ def test_process_join_with_socket_already_closed () -> None :
109+ """Test that join handles an already-closed parent socket gracefully."""
110+ process = Process (Config (app = app ), target = run , sockets = [])
111+ process .start ()
112+ time .sleep (0.5 )
113+ os .close (process .parent_sock .fileno ())
114+ process .terminate ()
115+ process .join ()
116+
117+
118+ @new_console_in_windows
119+ def test_handle_int () -> None :
120+ config = Config (app = app , workers = 2 )
121+ supervisor = Multiprocess (config , target = run , sockets = [])
122+ assert not supervisor .should_exit .is_set ()
123+ supervisor .handle_int ()
124+ assert supervisor .should_exit .is_set ()
125+
126+
127+ @new_console_in_windows
128+ def test_handle_term () -> None :
129+ config = Config (app = app , workers = 2 )
130+ supervisor = Multiprocess (config , target = run , sockets = [])
131+ assert not supervisor .should_exit .is_set ()
132+ supervisor .handle_term ()
133+ assert supervisor .should_exit .is_set ()
134+
135+
136+ @new_console_in_windows
137+ def test_keep_subprocess_alive_noop_when_exiting () -> None :
138+ config = Config (app = app , workers = 2 )
139+ supervisor = Multiprocess (config , target = run , sockets = [])
140+ supervisor .should_exit .set ()
141+ supervisor .keep_subprocess_alive ()
142+
143+
97144@new_console_in_windows
98145def test_multiprocess_run () -> None :
99146 """
0 commit comments