1- #! /usr/bin/env python3
2-
3- # This script is run (remotely) on a DAQ node to stop recording
4- # - get the PID of the hashpipe process
5- # - send it a SIGINT signal
6- # - wait for it to exit
7- #
8- # Then kill any other hashpipe processes
9- #
10- # On success, print OK. Otherwise print an error message
11-
12- import os , signal , sys
1+ import os , signal , sys , time
132sys .path .append ('/app/' )
143import control_util as util
4+ import psutil
5+
6+ GRACE_SECONDS = 5.0
7+
8+ def _send_sigint_to_pid (pid : int ):
9+ try :
10+ p = psutil .Process (pid )
11+ if p .name () == util .hashpipe_name :
12+ os .kill (pid , signal .SIGINT )
13+ return True
14+ except Exception :
15+ pass
16+ return False
17+
18+ def _any_hashpipe_pids ():
19+ pids = []
20+ for p in psutil .process_iter (attrs = ["pid" ,"name" ]):
21+ try :
22+ if p .info ["name" ] == util .hashpipe_name :
23+ pids .append (p .info ["pid" ])
24+ except Exception :
25+ continue
26+ return pids
27+
28+ def _wait_for_exit (pids , timeout_s ):
29+ deadline = time .time () + timeout_s
30+ while time .time () < deadline :
31+ alive = []
32+ for pid in pids :
33+ try :
34+ os .kill (pid , 0 )
35+ alive .append (pid )
36+ except Exception :
37+ pass
38+ if not alive :
39+ return True
40+ time .sleep (0.1 )
41+ return False
1542
1643def main ():
44+ # 1) Try SIGINT to the recorded PID if present
45+ recorded_pid = None
1746 try :
18- f = open (util .daq_hashpipe_pid_filename , 'r' )
19- except :
20- f = None
21- if f :
22- pid = int (f .read ())
23- f .close ()
24- if not util .stop_hashpipe (pid ):
25- print ("Couldn't stop hashpipe" )
26- os .unlink (util .daq_hashpipe_pid_filename )
27-
28- util .kill_hashpipe ()
29-
30- # if the HK recorder is running on a remote DAQ, we didn't start it.
31- # But it shouldn't be there, so kill it
32- util .kill_hk_recorder ()
47+ with open (util .daq_hashpipe_pid_filename , 'r' ) as f :
48+ recorded_pid = int (f .read ().strip ())
49+ except Exception :
50+ recorded_pid = None
51+
52+ sent = False
53+ target_pids = []
54+ if recorded_pid and _send_sigint_to_pid (recorded_pid ):
55+ sent = True
56+ target_pids = [recorded_pid ]
57+ else :
58+ # 2) No valid recorded PID: send SIGINT to all hashpipe processes
59+ hp_pids = _any_hashpipe_pids ()
60+ for pid in hp_pids :
61+ try :
62+ os .kill (pid , signal .SIGINT )
63+ sent = True
64+ except Exception :
65+ pass
66+ target_pids = hp_pids
67+
68+ # 3) Wait briefly for graceful exit; if still alive, SIGKILL them
69+ if target_pids :
70+ if not _wait_for_exit (target_pids , GRACE_SECONDS ):
71+ # escalate
72+ for pid in target_pids :
73+ try :
74+ os .kill (pid , signal .SIGKILL )
75+ except Exception :
76+ pass
77+ # Wait one more short interval to ensure death
78+ _wait_for_exit (target_pids , 1.0 )
79+
80+ # 4) As a final safety, if any hashpipe remains, kill them (covers races)
81+ residual = _any_hashpipe_pids ()
82+ if residual :
83+ for pid in residual :
84+ try :
85+ os .kill (pid , signal .SIGKILL )
86+ except Exception :
87+ pass
88+
89+ # 5) Cleanup pid file and auxiliary daemons
90+ try :
91+ if os .path .exists (util .daq_hashpipe_pid_filename ):
92+ os .unlink (util .daq_hashpipe_pid_filename )
93+ except Exception :
94+ pass
95+
96+ # HK recorder shouldn’t run in CI; ensure it’s not left behind
97+ try :
98+ util .kill_hk_recorder ()
99+ except Exception :
100+ pass
33101
34102 try :
35103 os .unlink (util .daq_run_name_filename )
36- except :
104+ except Exception :
37105 pass
38106
39107 print ('stop_daq.py: OK' )
40108
41- main ()
109+ if __name__ == '__main__' :
110+ main ()
0 commit comments