66"""
77
88try :
9+ import os
910 import signal
1011 import sys
1112 import time
1213 import threading
14+ import traceback
1315
1416 from enum import Enum
1517 from sonic_py_common import daemon_base , device_info , logger
@@ -94,10 +96,14 @@ def handle_state_update_task(port, fvp_dict, y_cable_presence, stopping_event):
9496# Thread wrapper class to update ycable info periodically
9597
9698
97- class YcableInfoUpdateTask (object ):
98- def __init__ (self ):
99- self .task_thread = None
99+
100+ class YcableInfoUpdateTask (threading .Thread ):
101+
102+ def __init__ (self , y_cable_presence ):
103+ threading .Thread .__init__ (self )
104+ self .exc = None
100105 self .task_stopping_event = threading .Event ()
106+ self .y_cable_presence = y_cable_presence
101107 self .table_helper = y_cable_table_helper .YcableInfoUpdateTableHelper ()
102108
103109
@@ -122,25 +128,36 @@ def task_worker(self, y_cable_presence):
122128
123129 helper_logger .log_info ("Stop DOM monitoring loop" )
124130
125- def task_run (self , y_cable_presence ):
131+ def run (self ):
126132 if self .task_stopping_event .is_set ():
127133 return
128134
129- self .task_thread = threading .Thread (target = self .task_worker , args = (y_cable_presence ,))
130- self .task_thread .start ()
135+ try :
136+ self .task_worker (self .y_cable_presence )
137+ except Exception as e :
138+ helper_logger .log_error ("Exception occured at child thread YcableInfoUpdateTask due to {} {}" .format (repr (e ), traceback .format_exc ()))
139+
140+ self .exc = e
131141
132- def task_stop (self ):
133- self .task_stopping_event .set ()
134- self .task_thread .join ()
142+ def join (self ):
143+ threading .Thread .join (self )
144+
145+ if self .exc :
146+ raise self .exc
135147
136148# Process wrapper class to update sfp state info periodically
137149
138150
139- class YcableStateUpdateTask (object ):
140- def __init__ (self ):
141- self .task_process = None
151+
152+
153+ class YcableStateUpdateTask (threading .Thread ):
154+ def __init__ (self , sfp_error_event , y_cable_presence ):
155+ threading .Thread .__init__ (self )
156+ self .exc = None
142157 self .task_stopping_event = threading .Event ()
143158 self .sfp_insert_events = {}
159+ self .sfp_error_event = sfp_error_event
160+ self .y_cable_presence = y_cable_presence
144161 self .table_helper = y_cable_table_helper .YcableStateUpdateTableHelper ()
145162
146163
@@ -192,18 +209,21 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence):
192209
193210 handle_state_update_task (port , fvp_dict , y_cable_presence , stopping_event )
194211
195-
196- def task_run (self , sfp_error_event , y_cable_presence ):
212+ def run (self ):
197213 if self .task_stopping_event .is_set ():
198214 return
199215
200- self .task_process = threading .Thread (target = self .task_worker , args = (
201- self .task_stopping_event , sfp_error_event , y_cable_presence ))
202- self .task_process .start ()
216+ try :
217+ self .task_worker (self .task_stopping_event , self .sfp_error_event , self .y_cable_presence )
218+ except Exception as e :
219+ helper_logger .log_error ("Exception occured at child thread YcableStateUpdateTask due to {} {}" .format (repr (e ), traceback .format_exc ()))
220+ self .exc = e
221+
222+ def join (self ):
223+ threading .Thread .join (self )
203224
204- def task_stop (self ):
205- self .task_stopping_event .set ()
206- self .task_process .join ()
225+ if self .exc :
226+ raise self .exc
207227
208228#
209229# Daemon =======================================================================
@@ -220,6 +240,7 @@ def __init__(self, log_identifier):
220240 self .sfp_error_event = threading .Event ()
221241 self .y_cable_presence = [False ]
222242 self .table_helper = y_cable_table_helper .DaemonYcableTableHelper ()
243+ self .threads = []
223244
224245 # Signal handler
225246 def signal_handler (self , sig , frame ):
@@ -349,36 +370,58 @@ def run(self):
349370 self .init ()
350371
351372 # Start the ycable task update thread
352- ycable_info_update = YcableInfoUpdateTask ()
353- ycable_info_update .task_run (self .y_cable_presence )
373+ ycable_info_update = YcableInfoUpdateTask (self .y_cable_presence )
374+ ycable_info_update .start ()
375+ self .threads .append (ycable_info_update )
354376
355377 # Start the sfp state info update process
356- ycable_state_update = YcableStateUpdateTask ()
357- ycable_state_update .task_run (self .sfp_error_event , self .y_cable_presence )
378+ ycable_state_update = YcableStateUpdateTask (self .sfp_error_event , self .y_cable_presence )
379+ ycable_state_update .start ()
380+ self .threads .append (ycable_state_update )
358381
359382 # Start the Y-cable state info update process if Y cable presence established
360383 y_cable_state_worker_update = None
361384 if self .y_cable_presence [0 ] is True :
362385 y_cable_state_worker_update = y_cable_helper .YCableTableUpdateTask ()
363- y_cable_state_worker_update .task_run ()
386+ y_cable_state_worker_update .start ()
387+ self .threads .append (y_cable_state_worker_update )
388+ y_cable_cli_worker_update = y_cable_helper .YCableCliUpdateTask ()
389+ y_cable_cli_worker_update .start ()
390+ self .threads .append (y_cable_cli_worker_update )
364391
365392 # Start main loop
366393 self .log_info ("Start daemon main loop" )
367394
368395 while not self .stop_event .wait (self .timeout ):
369396 self .log_info ("Ycable main loop" )
397+ # check all threads are alive
398+ for thread in self .threads :
399+ if thread .is_alive () is False :
400+ try :
401+ thread .join ()
402+ except Exception as e :
403+ self .log_error ("Exception occured at child thread {} to {}" .format (thread .getName (), repr (e )))
404+ self .log_error ("thread id {} is not running, exiting main loop" .format (thread .getName ()))
405+ os .kill (os .getpid (), signal .SIGKILL )
370406
371- self .log_info ("Stop daemon main loop" )
407+
408+ self .log_error ("Stop daemon main loop" )
372409
373410 # Stop the ycable periodic info info update thread
374- ycable_info_update .task_stop ()
411+ if ycable_info_update .is_alive ():
412+ ycable_info_update .join ()
375413
376414 # Stop the ycable update process
377- ycable_state_update .task_stop ()
415+ if ycable_state_update .is_alive ():
416+ ycable_state_update .join ()
378417
379418 # Stop the Y-cable state info update process
380419 if self .y_cable_presence [0 ] is True :
381- y_cable_state_worker_update .task_stop ()
420+ if y_cable_state_worker_update .is_alive ():
421+ y_cable_state_worker_update .join ()
422+ if y_cable_cli_worker_update .is_alive ():
423+ y_cable_cli_worker_update .join ()
424+
382425
383426 # Start daemon deinitialization sequence
384427 self .deinit ()
0 commit comments