@@ -449,11 +449,41 @@ if __name__ == "__main__":
449449 available_port = find_available_port (start_port = 5100 , end_port = 5500 )
450450 print (f"Starting server on port { available_port } ..." )
451451 proc = subprocess .Popen (
452- ["pnpm" , "dev" , "--port" , str (available_port )], cwd = workflow_dir
452+ ["pnpm" , "dev" , "--port" , str (available_port )],
453+ cwd = workflow_dir ,
454+ start_new_session = True ,
455+ stdout = subprocess .PIPE ,
456+ stderr = subprocess .PIPE ,
453457 )
454458
459+ # Forward stdout/stderr in background threads; stopped before
460+ # shutdown to suppress BullMQ teardown errors and pnpm's
461+ # ELIFECYCLE message (Motia framework limitation).
462+ import threading
463+
464+ output_active = threading .Event ()
465+ output_active .set ()
466+
467+ def forward_stream (stream , dest ):
468+ for line in iter (stream .readline , b"" ):
469+ if not output_active .is_set ():
470+ break
471+ dest .write (line )
472+ dest .flush ()
473+
474+ threading .Thread (
475+ target = forward_stream ,
476+ args = (proc .stdout , sys .stdout .buffer ),
477+ daemon = True ,
478+ ).start ()
479+ threading .Thread (
480+ target = forward_stream ,
481+ args = (proc .stderr , sys .stderr .buffer ),
482+ daemon = True ,
483+ ).start ()
484+
455485 # Wait for service to start
456- max_retries = 30
486+ max_retries = 600
457487 for i in range (max_retries ):
458488 try :
459489 # Disable proxy, connect directly to localhost
@@ -506,10 +536,22 @@ if __name__ == "__main__":
506536 )
507537
508538 # 3. Shutdown service ================================
509- # Give observability plugin time to finish async operations (e.g., Redis writes)
539+ output_active .clear ()
540+ import signal
541+
510542 time .sleep (1 )
511- proc .terminate ()
512- proc .wait ()
543+ try :
544+ os .killpg (os .getpgid (proc .pid ), signal .SIGTERM )
545+ except ProcessLookupError :
546+ pass
547+ try :
548+ proc .wait (timeout = 10 )
549+ except subprocess .TimeoutExpired :
550+ try :
551+ os .killpg (os .getpgid (proc .pid ), signal .SIGKILL )
552+ except ProcessLookupError :
553+ pass
554+ proc .wait ()
513555 print (
514556 f"\n Task completed. Command running on http://localhost:{ available_port } is finished"
515557 )
0 commit comments