Skip to content

Commit 48d376d

Browse files
vladima1st1
authored andcommitted
Keep behavior of run_* consistent with event loops bundled in CPython: ensure that wakeup fd is non-modified if it was not changed before i.e. via calling add_signal_handler
1 parent 1765691 commit 48d376d

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

Diff for: tests/test_signals.py

+40
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,46 @@ async def coro():
271271
with self.assertRaisesRegex(TypeError, 'coroutines cannot be used'):
272272
self.loop.add_signal_handler(signal.SIGHUP, coro)
273273

274+
def test_wakeup_fd_unchanged(self):
275+
async def runner():
276+
PROG = R"""\
277+
import uvloop
278+
import signal
279+
import asyncio
280+
281+
282+
def get_wakeup_fd():
283+
fd = signal.set_wakeup_fd(-1)
284+
signal.set_wakeup_fd(fd)
285+
return fd
286+
287+
async def f(): pass
288+
289+
fd0 = get_wakeup_fd()
290+
loop = """ + self.NEW_LOOP + """
291+
try:
292+
asyncio.set_event_loop(loop)
293+
loop.run_until_complete(f())
294+
fd1 = get_wakeup_fd()
295+
finally:
296+
loop.close()
297+
298+
print(fd0 == fd1, flush=True)
299+
300+
"""
301+
302+
proc = await asyncio.create_subprocess_exec(
303+
sys.executable, b'-W', b'ignore', b'-c', PROG,
304+
stdout=subprocess.PIPE,
305+
stderr=subprocess.PIPE,
306+
loop=self.loop)
307+
308+
out, err = await proc.communicate()
309+
self.assertEqual(err, b'')
310+
self.assertIn(b'True', out)
311+
312+
self.loop.run_until_complete(runner())
313+
274314

275315
class Test_UV_Signals(_TestSignal, tb.UVTestCase):
276316
NEW_LOOP = 'uvloop.new_event_loop()'

Diff for: uvloop/loop.pyx

+13-5
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,16 @@ cdef class Loop:
241241
self._debug_exception_handler_cnt = 0
242242

243243
cdef _setup_signals(self):
244+
cdef int old_wakeup_fd
245+
244246
if self._listening_signals:
245247
return
246248

247249
self._ssock, self._csock = socket_socketpair()
248250
self._ssock.setblocking(False)
249251
self._csock.setblocking(False)
250252
try:
251-
_set_signal_wakeup_fd(self._csock.fileno())
253+
old_wakeup_fd = _set_signal_wakeup_fd(self._csock.fileno())
252254
except (OSError, ValueError):
253255
# Not the main thread
254256
self._ssock.close()
@@ -257,10 +259,12 @@ cdef class Loop:
257259
return
258260

259261
self._listening_signals = True
262+
return old_wakeup_fd
260263

261264
cdef _recv_signals_start(self):
265+
cdef object old_wakeup_fd = None
262266
if self._ssock is None:
263-
self._setup_signals()
267+
old_wakeup_fd = self._setup_signals()
264268
if self._ssock is None:
265269
# Not the main thread.
266270
return
@@ -272,6 +276,7 @@ cdef class Loop:
272276
"Loop._read_from_self",
273277
<method_t>self._read_from_self,
274278
self))
279+
return old_wakeup_fd
275280

276281
cdef _recv_signals_stop(self):
277282
if self._ssock is None:
@@ -445,6 +450,7 @@ cdef class Loop:
445450

446451
cdef _run(self, uv.uv_run_mode mode):
447452
cdef int err
453+
cdef object old_wakeup_fd
448454

449455
if self._closed == 1:
450456
raise RuntimeError('unable to start the loop; it was closed')
@@ -467,7 +473,7 @@ cdef class Loop:
467473
self.handler_check__exec_writes.start()
468474
self.handler_idle.start()
469475

470-
self._recv_signals_start()
476+
old_wakeup_fd = self._recv_signals_start()
471477

472478
if aio_set_running_loop is not None:
473479
aio_set_running_loop(self)
@@ -478,6 +484,8 @@ cdef class Loop:
478484
aio_set_running_loop(None)
479485

480486
self._recv_signals_stop()
487+
if old_wakeup_fd is not None:
488+
signal_set_wakeup_fd(old_wakeup_fd)
481489

482490
self.handler_check__exec_writes.stop()
483491
self.handler_idle.stop()
@@ -3218,9 +3226,9 @@ cdef __install_pymem():
32183226

32193227
cdef _set_signal_wakeup_fd(fd):
32203228
if PY37 and fd >= 0:
3221-
signal_set_wakeup_fd(fd, warn_on_full_buffer=False)
3229+
return signal_set_wakeup_fd(fd, warn_on_full_buffer=False)
32223230
else:
3223-
signal_set_wakeup_fd(fd)
3231+
return signal_set_wakeup_fd(fd)
32243232

32253233

32263234
cdef _warn_with_source(msg, cls, source):

0 commit comments

Comments
 (0)