@@ -491,6 +491,50 @@ def check_global_circuit_breaker():
491491 return False
492492
493493
494+ def stop_all_processes(kids, lock=None):
495+ """Stop all child processes and clean up, similar to mailmanctl stop.
496+
497+ Args:
498+ kids: Dictionary of child processes
499+ lock: Optional lock to release
500+ """
501+ # First send SIGTERM to all children
502+ for pid in list(kids.keys()):
503+ try:
504+ os.kill(pid, signal.SIGTERM)
505+ except OSError as e:
506+ if e.errno != errno.ESRCH:
507+ raise
508+
509+ # Wait for all children to exit
510+ while kids:
511+ try:
512+ pid, status = os.wait()
513+ if pid in kids:
514+ del kids[pid]
515+ except OSError as e:
516+ if e.errno == errno.ECHILD:
517+ break
518+ elif e.errno != errno.EINTR:
519+ raise
520+ continue
521+
522+ # Clean up PID file
523+ try:
524+ os.unlink(mm_cfg.PIDFILE)
525+ syslog('qrunner', 'Removed PID file: %s', mm_cfg.PIDFILE)
526+ except OSError as e:
527+ if e.errno != errno.ENOENT:
528+ syslog('error', 'Failed to remove PID file %s: %s', mm_cfg.PIDFILE, str(e))
529+
530+ # Release lock if provided
531+ if lock:
532+ try:
533+ lock.unlock(unconditionally=1)
534+ except Exception as e:
535+ syslog('error', 'Failed to release lock: %s', str(e))
536+
537+
494538def main():
495539 try:
496540 args = parse_args()
@@ -692,13 +736,8 @@ Master qrunner detected abnormal subprocess exit
692736 # Check global circuit breaker before restarting
693737 if restarting and check_global_circuit_breaker():
694738 syslog('error', 'Global circuit breaker triggered - stopping all runners')
695- # Stop all runners
696- for pid in list(kids.keys()):
697- try:
698- os.kill(pid, signal.SIGTERM)
699- except OSError as e:
700- if e.errno != errno.ESRCH:
701- raise
739+ # Stop all processes and clean up
740+ stop_all_processes(kids, lock)
702741 # Exit the main loop
703742 break
704743
0 commit comments