1
1
import importlib
2
2
import json
3
+ import multiprocessing
3
4
import os
4
5
import platform
5
6
import signal
6
7
import subprocess
7
8
import sys
8
- import threading
9
9
import time
10
10
import tomllib
11
11
from importlib .metadata import entry_points
@@ -223,21 +223,16 @@ def run(self):
223
223
# If plain.models is installed (common) then we
224
224
# will do a couple extra things before starting all of the app-related
225
225
# processes (this way they don't all have to db-wait or anything)
226
+ process = None
226
227
if find_spec ("plain.models" ) is not None :
227
228
# Use a custom signal to tell the main thread to add
228
229
# the app processes once the db is ready
229
230
signal .signal (signal .SIGUSR1 , self .start_app )
230
231
231
- def _thread (env ):
232
- subprocess .run (["plain" , "models" , "db-wait" ], env = env , check = True )
233
- subprocess .run (["plain" , "migrate" , "--backup" ], env = env , check = True )
234
- # preflight with db?
235
- os .kill (os .getpid (), signal .SIGUSR1 )
236
-
237
- thread = threading .Thread (
238
- target = _thread , daemon = True , args = (self .plain_env ,)
232
+ process = multiprocessing .Process (
233
+ target = _process_task , args = (self .plain_env ,)
239
234
)
240
- thread .start ()
235
+ process .start ()
241
236
else :
242
237
# Start the app processes immediately
243
238
self .start_app (None , None )
@@ -253,6 +248,14 @@ def _thread(env):
253
248
if services_pid :
254
249
services_pid .rm ()
255
250
251
+ # Make sure the process is terminated if it is still running
252
+ if process and process .is_alive ():
253
+ os .killpg (os .getpgid (process .pid ), signal .SIGTERM )
254
+ process .join (timeout = 3 )
255
+ if process .is_alive ():
256
+ os .killpg (os .getpgid (process .pid ), signal .SIGKILL )
257
+ process .join ()
258
+
256
259
return self .poncho .returncode
257
260
258
261
def start_app (self , signum , frame ):
@@ -439,3 +442,16 @@ def add_pyproject_run(self):
439
442
** data .get ("env" , {}),
440
443
}
441
444
self .poncho .add_process (name , data ["cmd" ], env = env )
445
+
446
+
447
+ def _process_task (env ):
448
+ # Make this process the leader of a new group which can be killed together if it doesn't finish
449
+ os .setsid ()
450
+
451
+ subprocess .run (["plain" , "models" , "db-wait" ], env = env , check = True )
452
+ subprocess .run (["plain" , "migrate" , "--backup" ], env = env , check = True )
453
+
454
+ # preflight with db?
455
+
456
+ # Send SIGUSR1 to the parent process so the parent's handler is invoked
457
+ os .kill (os .getppid (), signal .SIGUSR1 )
0 commit comments