@@ -149,7 +149,8 @@ cdef class Loop:
149
149
< method_t> self ._exec_queued_writes, self ))
150
150
151
151
self ._ssock = self ._csock = None
152
- self ._signal_handlers = None
152
+ self ._signal_handlers = {}
153
+ self ._listening_signals = False
153
154
154
155
self ._coroutine_wrapper_set = False
155
156
@@ -225,19 +226,22 @@ cdef class Loop:
225
226
self ._debug_exception_handler_cnt = 0
226
227
227
228
cdef _setup_signals(self ):
229
+ if self ._listening_signals:
230
+ return
231
+
228
232
self ._ssock, self ._csock = socket_socketpair()
229
233
self ._ssock.setblocking(False )
230
234
self ._csock.setblocking(False )
231
235
try :
232
236
signal_set_wakeup_fd(self ._csock.fileno())
233
- except ValueError :
237
+ except ( OSError , ValueError ) :
234
238
# Not the main thread
235
239
self ._ssock.close()
236
240
self ._csock.close()
237
241
self ._ssock = self ._csock = None
238
242
return
239
243
240
- self ._signal_handlers = {}
244
+ self ._listening_signals = True
241
245
242
246
cdef _recv_signals_start(self ):
243
247
if self ._ssock is None :
@@ -261,14 +265,29 @@ cdef class Loop:
261
265
self ._remove_reader(self ._ssock)
262
266
263
267
cdef _shutdown_signals(self ):
264
- if self ._signal_handlers is None :
268
+ if not self ._listening_signals :
265
269
return
270
+
266
271
for sig in list (self ._signal_handlers):
267
272
self .remove_signal_handler(sig)
268
- signal_set_wakeup_fd(- 1 )
273
+
274
+ if not self ._listening_signals:
275
+ # `remove_signal_handler` will call `_shutdown_signals` when
276
+ # removing last signal handler.
277
+ return
278
+
279
+ try :
280
+ signal_set_wakeup_fd(- 1 )
281
+ except (ValueError , OSError ) as exc:
282
+ aio_logger.info(' set_wakeup_fd(-1) failed: %s ' , exc)
283
+
269
284
self ._remove_reader(self ._ssock)
270
285
self ._ssock.close()
271
286
self ._csock.close()
287
+ self ._ssock = None
288
+ self ._csock = None
289
+
290
+ self ._listening_signals = False
272
291
273
292
cdef _read_from_self(self ):
274
293
while True :
@@ -2415,9 +2434,9 @@ cdef class Loop:
2415
2434
cdef:
2416
2435
Handle h
2417
2436
2418
- if self ._signal_handlers is None :
2437
+ if not self ._listening_signals :
2419
2438
self ._setup_signals()
2420
- if self ._signal_handlers is None :
2439
+ if not self ._listening_signals :
2421
2440
raise ValueError (' set_wakeup_fd only works in main thread' )
2422
2441
2423
2442
if (aio_iscoroutine(callback)
@@ -2441,9 +2460,20 @@ cdef class Loop:
2441
2460
self ._signal_handlers[sig] = h
2442
2461
2443
2462
try :
2463
+ # Register a dummy signal handler to ask Python to write the signal
2464
+ # number in the wakeup file descriptor.
2444
2465
signal_signal(sig, _sighandler_noop)
2466
+
2467
+ # Set SA_RESTART to limit EINTR occurrences.
2468
+ signal_siginterrupt(sig, False )
2445
2469
except OSError as exc:
2446
2470
del self ._signal_handlers[sig]
2471
+ if not self ._signal_handlers:
2472
+ try :
2473
+ signal_set_wakeup_fd(- 1 )
2474
+ except (ValueError , OSError ) as nexc:
2475
+ aio_logger.info(' set_wakeup_fd(-1) failed: %s ' , nexc)
2476
+
2447
2477
if exc.errno == errno_EINVAL:
2448
2478
raise RuntimeError (' sig {} cannot be caught' .format(sig))
2449
2479
else :
@@ -2456,7 +2486,7 @@ cdef class Loop:
2456
2486
"""
2457
2487
self ._check_signal(sig)
2458
2488
2459
- if self ._signal_handlers is None :
2489
+ if not self ._listening_signals :
2460
2490
return False
2461
2491
2462
2492
try :
@@ -2477,6 +2507,9 @@ cdef class Loop:
2477
2507
else :
2478
2508
raise
2479
2509
2510
+ if not self ._signal_handlers:
2511
+ self ._shutdown_signals()
2512
+
2480
2513
return True
2481
2514
2482
2515
async def create_datagram_endpoint(self , protocol_factory,
0 commit comments