Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d18ccd1

Browse files
committed
tets
1 parent 316b16d commit d18ccd1

5 files changed

Lines changed: 278 additions & 41 deletions

File tree

Doc/c-api/exceptions.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,20 @@ in various ways. There is a separate error indicator for each thread.
443443
444444
.. c:function:: int PySignal_SetWakeupFd(int fd)
445445
446-
This utility function specifies a file descriptor to which a ``'\0'`` byte will
447-
be written whenever a signal is received. It returns the previous such file
448-
descriptor. The value ``-1`` disables the feature; this is the initial state.
446+
This utility function specifies a file descriptor to which the signal number
447+
is written as a single byte whenever a signal is received. *fd* must be
448+
non-blocking. It returns the previous such file descriptor.
449+
450+
On Windows, the function only supports socket handles.
451+
452+
The value ``-1`` disables the feature; this is the initial state.
449453
This is equivalent to :func:`signal.set_wakeup_fd` in Python, but without any
450454
error checking. *fd* should be a valid file descriptor. The function should
451455
only be called from the main thread.
452456
457+
.. versionchanged:: 3.5
458+
On Windows, the function now only supports socket handles.
459+
453460
454461
.. c:function:: PyObject* PyErr_NewException(char *name, PyObject *base, PyObject *dict)
455462

Doc/library/signal.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ The :mod:`signal` module defines the following functions:
308308
a library to wakeup a poll or select call, allowing the signal to be fully
309309
processed.
310310

311+
On Windows, the function only supports socket handles.
312+
311313
The old wakeup fd is returned. *fd* must be non-blocking. It is up to the
312314
library to remove any bytes before calling poll or select again.
313315

@@ -318,6 +320,9 @@ The :mod:`signal` module defines the following functions:
318320
attempting to call it from other threads will cause a :exc:`ValueError`
319321
exception to be raised.
320322

323+
.. versionchanged:: 3.5
324+
On Windows, the function now only supports socket handles.
325+
321326

322327
.. function:: siginterrupt(signalnum, flag)
323328

Lib/test/test_signal.py

Lines changed: 119 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pickle
77
import select
88
import signal
9+
import socket
910
import struct
1011
import subprocess
1112
import traceback
@@ -251,21 +252,43 @@ def test_issue9324(self):
251252
class WakeupFDTests(unittest.TestCase):
252253

253254
def test_invalid_fd(self):
254-
fd = support.make_bad_fd()
255+
if sys.platform == "win32":
256+
sock = socket.socket()
257+
fd = sock.fileno()
258+
sock.close()
259+
else:
260+
fd = support.make_bad_fd()
255261
self.assertRaises((ValueError, OSError),
256262
signal.set_wakeup_fd, fd)
257263

264+
@unittest.skipUnless(sys.platform == "win32", 'test specific to Windows')
265+
def test_only_socket(self):
266+
# set_wakeup_fd() expects a socket on Windows
267+
with open(support.TESTFN, 'wb') as fp:
268+
self.addCleanup(support.unlink, support.TESTFN)
269+
self.assertRaises(ValueError,
270+
signal.set_wakeup_fd, fp.fileno())
271+
258272
def test_set_wakeup_fd_result(self):
259-
r1, w1 = os.pipe()
260-
self.addCleanup(os.close, r1)
261-
self.addCleanup(os.close, w1)
262-
r2, w2 = os.pipe()
263-
self.addCleanup(os.close, r2)
264-
self.addCleanup(os.close, w2)
265-
266-
signal.set_wakeup_fd(w1)
267-
self.assertIs(signal.set_wakeup_fd(w2), w1)
268-
self.assertIs(signal.set_wakeup_fd(-1), w2)
273+
if sys.platform == 'win32':
274+
sock1 = socket.socket()
275+
self.addCleanup(sock1.close)
276+
fd1 = sock1.fileno()
277+
278+
sock2 = socket.socket()
279+
self.addCleanup(sock2.close)
280+
fd2 = sock2.fileno()
281+
else:
282+
r1, fd1 = os.pipe()
283+
self.addCleanup(os.close, r1)
284+
self.addCleanup(os.close, fd1)
285+
r2, fd2 = os.pipe()
286+
self.addCleanup(os.close, r2)
287+
self.addCleanup(os.close, fd2)
288+
289+
signal.set_wakeup_fd(fd1)
290+
self.assertIs(signal.set_wakeup_fd(fd2), fd1)
291+
self.assertIs(signal.set_wakeup_fd(-1), fd2)
269292
self.assertIs(signal.set_wakeup_fd(-1), -1)
270293

271294

@@ -441,6 +464,90 @@ def test_pending(self):
441464
""", signal.SIGUSR1, signal.SIGUSR2, ordered=False)
442465

443466

467+
@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
468+
class WakeupSocketSignalTests(unittest.TestCase):
469+
470+
@unittest.skipIf(_testcapi is None, 'need _testcapi')
471+
def test_socket(self):
472+
# use a subprocess to have only one thread
473+
code = """if 1:
474+
import signal
475+
import socket
476+
import struct
477+
import _testcapi
478+
479+
signum = signal.SIGINT
480+
signals = (signum,)
481+
482+
def handler(signum, frame):
483+
pass
484+
485+
signal.signal(signum, handler)
486+
487+
read, write = socket.socketpair()
488+
read.setblocking(False)
489+
write.setblocking(False)
490+
signal.set_wakeup_fd(write.fileno())
491+
492+
_testcapi.raise_signal(signum)
493+
494+
data = read.recv(1)
495+
if not data:
496+
raise Exception("no signum written")
497+
raised = struct.unpack('B', data)
498+
if raised != signals:
499+
raise Exception("%r != %r" % (raised, signals))
500+
501+
read.close()
502+
write.close()
503+
"""
504+
505+
assert_python_ok('-c', code)
506+
507+
@unittest.skipIf(_testcapi is None, 'need _testcapi')
508+
def test_send_error(self):
509+
# Use a subprocess to have only one thread.
510+
if os.name == 'nt':
511+
action = 'send'
512+
else:
513+
action = 'write'
514+
code = """if 1:
515+
import errno
516+
import signal
517+
import socket
518+
import sys
519+
import time
520+
import _testcapi
521+
from test.support import captured_stderr
522+
523+
signum = signal.SIGINT
524+
525+
def handler(signum, frame):
526+
pass
527+
528+
signal.signal(signum, handler)
529+
530+
read, write = socket.socketpair()
531+
read.setblocking(False)
532+
write.setblocking(False)
533+
534+
signal.set_wakeup_fd(write.fileno())
535+
536+
# Close sockets: send() will fail
537+
read.close()
538+
write.close()
539+
540+
with captured_stderr() as err:
541+
_testcapi.raise_signal(signum)
542+
543+
err = err.getvalue()
544+
if ('Exception ignored when trying to {action} to the signal wakeup fd'
545+
not in err):
546+
raise AssertionError(err)
547+
""".format(action=action)
548+
assert_python_ok('-c', code)
549+
550+
444551
@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
445552
class SiginterruptTest(unittest.TestCase):
446553

@@ -990,6 +1097,7 @@ def test_main():
9901097
try:
9911098
support.run_unittest(GenericTests, PosixTests, InterProcessSignalTests,
9921099
WakeupFDTests, WakeupSignalTests,
1100+
WakeupSocketSignalTests,
9931101
SiginterruptTest, ItimerTest, WindowsSignalTests,
9941102
PendingSignalsTests)
9951103
finally:

0 commit comments

Comments
 (0)