@@ -57,41 +57,47 @@ def __init__(self) -> None:
5757 self ._startup_error : BaseException | None = None
5858 self ._close_requested = False
5959 self ._lock = threading .Lock ()
60+ self ._operation_lock = threading .Lock ()
6061
6162 def run (self , awaitable : Awaitable [Any ]) -> Any :
62- loop = self ._ensure_loop ()
63- future = asyncio .run_coroutine_threadsafe (self ._await_result (awaitable ), loop )
64- return future .result ()
63+ with self ._operation_lock :
64+ loop = self ._ensure_loop ()
65+ future = asyncio .run_coroutine_threadsafe (
66+ self ._await_result (awaitable ), loop
67+ )
68+ return future .result ()
6569
6670 def close (self ) -> None :
71+ current = threading .current_thread ()
6772 with self ._lock :
68- loop = self ._loop
69- thread = self ._thread
70- if thread is None :
73+ if current is self ._thread and self ._loop is not None :
74+ self ._loop .call_soon (self ._loop .stop )
7175 return
72- if loop is None :
73- self ._close_requested = True
74- else :
75- self ._loop = None
76- self ._thread = None
77- self ._closing_threads .add (thread )
78-
79- if loop is None :
80- if thread is not threading .current_thread ():
81- thread .join ()
82- return
8376
84- if loop . is_closed () :
77+ with self . _operation_lock :
8578 with self ._lock :
86- self ._closing_threads .discard (thread )
87- return
79+ loop = self ._loop
80+ thread = self ._thread
81+ if thread is None :
82+ return
83+ if loop is None :
84+ self ._close_requested = True
85+ else :
86+ self ._loop = None
87+ self ._thread = None
88+ self ._closing_threads .add (thread )
8889
89- if thread is threading .current_thread ():
90- loop .call_soon (loop .stop )
91- return
90+ if loop is None :
91+ thread .join ()
92+ return
93+
94+ if loop .is_closed ():
95+ with self ._lock :
96+ self ._closing_threads .discard (thread )
97+ return
9298
93- loop .call_soon_threadsafe (loop .stop )
94- thread .join ()
99+ loop .call_soon_threadsafe (loop .stop )
100+ thread .join ()
95101
96102 def owns_thread (self , thread : threading .Thread ) -> bool :
97103 with self ._lock :
@@ -130,10 +136,13 @@ def _ensure_loop(self) -> asyncio.AbstractEventLoop:
130136 return self ._loop
131137
132138 def _run_loop (self ) -> None :
139+ loop = None
133140 try :
134141 loop = _ContextEventLoop ()
135142 asyncio .set_event_loop (loop )
136143 except BaseException as error :
144+ if loop is not None and not loop .is_closed ():
145+ loop .close ()
137146 with self ._lock :
138147 self ._startup_error = error
139148 self ._thread = None
0 commit comments