6
6
"""
7
7
8
8
try :
9
+ import os
9
10
import signal
10
11
import sys
11
12
import time
12
13
import threading
14
+ import traceback
13
15
14
16
from enum import Enum
15
17
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):
94
96
# Thread wrapper class to update ycable info periodically
95
97
96
98
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
100
105
self .task_stopping_event = threading .Event ()
106
+ self .y_cable_presence = y_cable_presence
101
107
self .table_helper = y_cable_table_helper .YcableInfoUpdateTableHelper ()
102
108
103
109
@@ -122,25 +128,36 @@ def task_worker(self, y_cable_presence):
122
128
123
129
helper_logger .log_info ("Stop DOM monitoring loop" )
124
130
125
- def task_run (self , y_cable_presence ):
131
+ def run (self ):
126
132
if self .task_stopping_event .is_set ():
127
133
return
128
134
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
131
141
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
135
147
136
148
# Process wrapper class to update sfp state info periodically
137
149
138
150
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
142
157
self .task_stopping_event = threading .Event ()
143
158
self .sfp_insert_events = {}
159
+ self .sfp_error_event = sfp_error_event
160
+ self .y_cable_presence = y_cable_presence
144
161
self .table_helper = y_cable_table_helper .YcableStateUpdateTableHelper ()
145
162
146
163
@@ -192,18 +209,21 @@ def task_worker(self, stopping_event, sfp_error_event, y_cable_presence):
192
209
193
210
handle_state_update_task (port , fvp_dict , y_cable_presence , stopping_event )
194
211
195
-
196
- def task_run (self , sfp_error_event , y_cable_presence ):
212
+ def run (self ):
197
213
if self .task_stopping_event .is_set ():
198
214
return
199
215
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 )
203
224
204
- def task_stop (self ):
205
- self .task_stopping_event .set ()
206
- self .task_process .join ()
225
+ if self .exc :
226
+ raise self .exc
207
227
208
228
#
209
229
# Daemon =======================================================================
@@ -220,6 +240,7 @@ def __init__(self, log_identifier):
220
240
self .sfp_error_event = threading .Event ()
221
241
self .y_cable_presence = [False ]
222
242
self .table_helper = y_cable_table_helper .DaemonYcableTableHelper ()
243
+ self .threads = []
223
244
224
245
# Signal handler
225
246
def signal_handler (self , sig , frame ):
@@ -349,36 +370,58 @@ def run(self):
349
370
self .init ()
350
371
351
372
# 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 )
354
376
355
377
# 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 )
358
381
359
382
# Start the Y-cable state info update process if Y cable presence established
360
383
y_cable_state_worker_update = None
361
384
if self .y_cable_presence [0 ] is True :
362
385
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 )
364
391
365
392
# Start main loop
366
393
self .log_info ("Start daemon main loop" )
367
394
368
395
while not self .stop_event .wait (self .timeout ):
369
396
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 )
370
406
371
- self .log_info ("Stop daemon main loop" )
407
+
408
+ self .log_error ("Stop daemon main loop" )
372
409
373
410
# 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 ()
375
413
376
414
# Stop the ycable update process
377
- ycable_state_update .task_stop ()
415
+ if ycable_state_update .is_alive ():
416
+ ycable_state_update .join ()
378
417
379
418
# Stop the Y-cable state info update process
380
419
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
+
382
425
383
426
# Start daemon deinitialization sequence
384
427
self .deinit ()
0 commit comments