@@ -38,36 +38,36 @@ def _polling_thread_impl(
38
38
app_session_ref : "weakref.ReferenceType[AppSession]" ,
39
39
callback : Callback ,
40
40
):
41
- # Use polling because event-based methods are not available
42
- # to observe the session lifecycle.
43
41
while True :
44
42
app_session = app_session_ref ()
45
43
if not app_session :
46
- logger .debug ("AppSession has removed." )
44
+ logger .debug ("AppSession has been removed." )
47
45
break
48
46
if app_session ._state == AppSessionState .SHUTDOWN_REQUESTED :
49
- logger .debug (
50
- "AppSession %s has been requested to shutdown." ,
51
- app_session .id ,
52
- )
47
+ logger .debug ("AppSession %s shutdown requested." , app_session .id )
53
48
break
54
49
if self ._polling_thread_stop_event .wait (1.0 ):
55
- logger .debug (
56
- "The polling thread should be stopped. Exit the polling loop and return."
57
- )
50
+ logger .debug ("Polling thread stop requested. Exiting loop." )
58
51
return
59
52
60
- # Ensure the flag is set
61
53
self ._polling_thread_stop_event .set ()
62
-
63
- logger .debug ("AppSession shutdown has been detected." )
54
+ logger .debug ("AppSession shutdown detected." )
64
55
callback ()
65
56
66
- def stop (self ):
67
- if self ._polling_thread_stop_event .is_set ():
57
+ def stop (self , timeout : float = 1.0 ) -> None :
58
+ """
59
+ Stop the polling thread cleanly so we don't leak ShutdownPolling_* threads.
60
+ """
61
+ if not self ._polling_thread :
68
62
return
69
63
70
- if self ._polling_thread :
71
- self ._polling_thread_stop_event .set ()
72
- self ._polling_thread .join ()
73
- self ._polling_thread = None
64
+ self ._polling_thread_stop_event .set ()
65
+
66
+ if self ._polling_thread .is_alive ():
67
+ try :
68
+ self ._polling_thread .join (timeout = timeout )
69
+ except Exception :
70
+ logger .exception ("Failed to join ShutdownPolling thread" )
71
+
72
+ self ._polling_thread = None
73
+
0 commit comments