summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2014-07-24 20:51:05 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2014-07-24 20:51:05 (GMT)
commit1d8948e02385a6a2431b3ca782cc64eb39bc8a26 (patch)
treee4017426e09abcf1fd5e4fbe2778fe126415f10d
parent31f1a360b8aa3b80c0f23ce0d3dee592d1afefd9 (diff)
downloadcpython-1d8948e02385a6a2431b3ca782cc64eb39bc8a26.zip
cpython-1d8948e02385a6a2431b3ca782cc64eb39bc8a26.tar.gz
cpython-1d8948e02385a6a2431b3ca782cc64eb39bc8a26.tar.bz2
Backout 42ced0d023cd: oops, i didn't want to push this changeset :-/
-rw-r--r--Doc/c-api/exceptions.rst13
-rw-r--r--Doc/library/signal.rst5
-rw-r--r--Lib/test/test_signal.py130
-rw-r--r--Modules/signalmodule.c155
-rw-r--r--PCbuild/pythoncore.vcxproj16
5 files changed, 41 insertions, 278 deletions
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst
index 46033ca..33b4439 100644
--- a/Doc/c-api/exceptions.rst
+++ b/Doc/c-api/exceptions.rst
@@ -443,20 +443,13 @@ in various ways. There is a separate error indicator for each thread.
.. c:function:: int PySignal_SetWakeupFd(int fd)
- This utility function specifies a file descriptor to which the signal number
- is written as a single byte whenever a signal is received. *fd* must be
- non-blocking. It returns the previous such file descriptor.
-
- On Windows, the function only supports socket handles.
-
- The value ``-1`` disables the feature; this is the initial state.
+ This utility function specifies a file descriptor to which a ``'\0'`` byte will
+ be written whenever a signal is received. It returns the previous such file
+ descriptor. The value ``-1`` disables the feature; this is the initial state.
This is equivalent to :func:`signal.set_wakeup_fd` in Python, but without any
error checking. *fd* should be a valid file descriptor. The function should
only be called from the main thread.
- .. versionchanged:: 3.5
- On Windows, the function now only supports socket handles.
-
.. c:function:: PyObject* PyErr_NewException(char *name, PyObject *base, PyObject *dict)
diff --git a/Doc/library/signal.rst b/Doc/library/signal.rst
index cda228b..a97ce66 100644
--- a/Doc/library/signal.rst
+++ b/Doc/library/signal.rst
@@ -308,8 +308,6 @@ The :mod:`signal` module defines the following functions:
a library to wakeup a poll or select call, allowing the signal to be fully
processed.
- On Windows, the function only supports socket handles.
-
The old wakeup fd is returned. *fd* must be non-blocking. It is up to the
library to remove any bytes before calling poll or select again.
@@ -320,9 +318,6 @@ The :mod:`signal` module defines the following functions:
attempting to call it from other threads will cause a :exc:`ValueError`
exception to be raised.
- .. versionchanged:: 3.5
- On Windows, the function now only supports socket handles.
-
.. function:: siginterrupt(signalnum, flag)
diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py
index 28bb4d6..56ab631 100644
--- a/Lib/test/test_signal.py
+++ b/Lib/test/test_signal.py
@@ -6,7 +6,6 @@ import gc
import pickle
import select
import signal
-import socket
import struct
import subprocess
import traceback
@@ -252,43 +251,21 @@ class WindowsSignalTests(unittest.TestCase):
class WakeupFDTests(unittest.TestCase):
def test_invalid_fd(self):
- if sys.platform == "win32":
- sock = socket.socket()
- fd = sock.fileno()
- sock.close()
- else:
- fd = support.make_bad_fd()
+ fd = support.make_bad_fd()
self.assertRaises((ValueError, OSError),
signal.set_wakeup_fd, fd)
- @unittest.skipUnless(sys.platform == "win32", 'test specific to Windows')
- def test_only_socket(self):
- # set_wakeup_fd() expects a socket on Windows
- with open(support.TESTFN, 'wb') as fp:
- self.addCleanup(support.unlink, support.TESTFN)
- self.assertRaises(ValueError,
- signal.set_wakeup_fd, fp.fileno())
-
def test_set_wakeup_fd_result(self):
- if sys.platform == 'win32':
- sock1 = socket.socket()
- self.addCleanup(sock1.close)
- fd1 = sock1.fileno()
-
- sock2 = socket.socket()
- self.addCleanup(sock2.close)
- fd2 = sock2.fileno()
- else:
- r1, fd1 = os.pipe()
- self.addCleanup(os.close, r1)
- self.addCleanup(os.close, fd1)
- r2, fd2 = os.pipe()
- self.addCleanup(os.close, r2)
- self.addCleanup(os.close, fd2)
-
- signal.set_wakeup_fd(fd1)
- self.assertIs(signal.set_wakeup_fd(fd2), fd1)
- self.assertIs(signal.set_wakeup_fd(-1), fd2)
+ r1, w1 = os.pipe()
+ self.addCleanup(os.close, r1)
+ self.addCleanup(os.close, w1)
+ r2, w2 = os.pipe()
+ self.addCleanup(os.close, r2)
+ self.addCleanup(os.close, w2)
+
+ signal.set_wakeup_fd(w1)
+ self.assertIs(signal.set_wakeup_fd(w2), w1)
+ self.assertIs(signal.set_wakeup_fd(-1), w2)
self.assertIs(signal.set_wakeup_fd(-1), -1)
@@ -464,90 +441,6 @@ class WakeupSignalTests(unittest.TestCase):
""", signal.SIGUSR1, signal.SIGUSR2, ordered=False)
-@unittest.skipUnless(hasattr(socket, 'socketpair'), 'need socket.socketpair')
-class WakeupSocketSignalTests(unittest.TestCase):
-
- @unittest.skipIf(_testcapi is None, 'need _testcapi')
- def test_socket(self):
- # use a subprocess to have only one thread
- code = """if 1:
- import signal
- import socket
- import struct
- import _testcapi
-
- signum = signal.SIGINT
- signals = (signum,)
-
- def handler(signum, frame):
- pass
-
- signal.signal(signum, handler)
-
- read, write = socket.socketpair()
- read.setblocking(False)
- write.setblocking(False)
- signal.set_wakeup_fd(write.fileno())
-
- _testcapi.raise_signal(signum)
-
- data = read.recv(1)
- if not data:
- raise Exception("no signum written")
- raised = struct.unpack('B', data)
- if raised != signals:
- raise Exception("%r != %r" % (raised, signals))
-
- read.close()
- write.close()
- """
-
- assert_python_ok('-c', code)
-
- @unittest.skipIf(_testcapi is None, 'need _testcapi')
- def test_send_error(self):
- # Use a subprocess to have only one thread.
- if os.name == 'nt':
- action = 'send'
- else:
- action = 'write'
- code = """if 1:
- import errno
- import signal
- import socket
- import sys
- import time
- import _testcapi
- from test.support import captured_stderr
-
- signum = signal.SIGINT
-
- def handler(signum, frame):
- pass
-
- signal.signal(signum, handler)
-
- read, write = socket.socketpair()
- read.setblocking(False)
- write.setblocking(False)
-
- signal.set_wakeup_fd(write.fileno())
-
- # Close sockets: send() will fail
- read.close()
- write.close()
-
- with captured_stderr() as err:
- _testcapi.raise_signal(signum)
-
- err = err.getvalue()
- if ('Exception ignored when trying to {action} to the signal wakeup fd'
- not in err):
- raise AssertionError(err)
- """.format(action=action)
- assert_python_ok('-c', code)
-
-
@unittest.skipIf(sys.platform == "win32", "Not valid on Windows")
class SiginterruptTest(unittest.TestCase):
@@ -1097,7 +990,6 @@ def test_main():
try:
support.run_unittest(GenericTests, PosixTests, InterProcessSignalTests,
WakeupFDTests, WakeupSignalTests,
- WakeupSocketSignalTests,
SiginterruptTest, ItimerTest, WindowsSignalTests,
PendingSignalsTests)
finally:
diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c
index a315f23..c4f0121 100644
--- a/Modules/signalmodule.c
+++ b/Modules/signalmodule.c
@@ -4,9 +4,6 @@
/* XXX Signals should be recorded per thread, now we have thread state. */
#include "Python.h"
-#ifdef MS_WINDOWS
-#include "socketmodule.h" /* needed for SOCKET_T */
-#endif
#ifndef MS_WINDOWS
#include "posixmodule.h"
#endif
@@ -90,18 +87,7 @@ static volatile struct {
PyObject *func;
} Handlers[NSIG];
-#ifdef MS_WINDOWS
-#define INVALID_SOCKET ((SOCKET_T)-1)
-
-static volatile struct {
- SOCKET_T fd;
- int send_err_set;
- int send_errno;
- int send_win_error;
-} wakeup = {INVALID_SOCKET, 0, 0};
-#else
static volatile sig_atomic_t wakeup_fd = -1;
-#endif
/* Speed up sigcheck() when none tripped */
static volatile sig_atomic_t is_tripped = 0;
@@ -185,33 +171,6 @@ checksignals_witharg(void * unused)
return PyErr_CheckSignals();
}
-#ifdef MS_WINDOWS
-static int
-report_wakeup_error(void* Py_UNUSED(data))
-{
- PyObject *res;
-
- if (wakeup.send_win_error) {
- /* PyErr_SetExcFromWindowsErr() invokes FormatMessage() which
- recognizes the error codes used by both GetLastError() and
- WSAGetLastError */
- res = PyErr_SetExcFromWindowsErr(PyExc_OSError, wakeup.send_win_error);
- }
- else {
- errno = wakeup.send_errno;
- res = PyErr_SetFromErrno(PyExc_OSError);
- }
-
- assert(res == NULL);
- wakeup.send_err_set = 0;
-
- PySys_WriteStderr("Exception ignored when trying to send to the "
- "signal wakeup fd:\n");
- PyErr_WriteUnraisable(NULL);
-
- return 0;
-}
-#else
static int
report_wakeup_error(void *data)
{
@@ -224,51 +183,26 @@ report_wakeup_error(void *data)
errno = save_errno;
return 0;
}
-#endif
static void
trip_signal(int sig_num)
{
unsigned char byte;
- Py_ssize_t rc;
+ int rc = 0;
Handlers[sig_num].tripped = 1;
-
-#ifdef MS_WINDOWS
- if (wakeup.fd != INVALID_SOCKET) {
- byte = (unsigned char)sig_num;
- do {
- rc = send(wakeup.fd, &byte, 1, 0);
- } while (rc < 0 && errno == EINTR);
-
- /* we only have a storage for one error in the wakeup structure */
- if (rc < 0 && !wakeup.send_err_set) {
- wakeup.send_err_set = 1;
- wakeup.send_errno = errno;
- wakeup.send_win_error = GetLastError();
- Py_AddPendingCall(report_wakeup_error, NULL);
- }
- }
-#else
if (wakeup_fd != -1) {
byte = (unsigned char)sig_num;
- do {
- rc = write(wakeup_fd, &byte, 1);
- } while (rc < 0 && errno == EINTR);
-
- if (rc < 0) {
- Py_AddPendingCall(report_wakeup_error,
- (void *)(Py_intptr_t)errno);
- }
- }
-#endif
-
- if (!is_tripped) {
- /* Set is_tripped after setting .tripped, as it gets
- cleared in PyErr_CheckSignals() before .tripped. */
- is_tripped = 1;
- Py_AddPendingCall(checksignals_witharg, NULL);
+ while ((rc = write(wakeup_fd, &byte, 1)) == -1 && errno == EINTR);
+ if (rc == -1)
+ Py_AddPendingCall(report_wakeup_error, (void *) (Py_intptr_t) errno);
}
+ if (is_tripped)
+ return;
+ /* Set is_tripped after setting .tripped, as it gets
+ cleared in PyErr_CheckSignals() before .tripped. */
+ is_tripped = 1;
+ Py_AddPendingCall(checksignals_witharg, NULL);
}
static void
@@ -492,28 +426,10 @@ signal_siginterrupt(PyObject *self, PyObject *args)
static PyObject *
signal_set_wakeup_fd(PyObject *self, PyObject *args)
{
-#ifdef MS_WINDOWS
- PyObject *fdobj;
- SOCKET_T fd, old_fd;
- int res;
- int res_size = sizeof res;
- PyObject *mod;
- struct stat st;
-
- if (!PyArg_ParseTuple(args, "O:set_wakeup_fd", &fdobj))
- return NULL;
-
- fd = PyLong_AsSocket_t(fdobj);
- if (fd == (SOCKET_T)(-1) && PyErr_Occurred())
- return NULL;
-#else
+ struct stat buf;
int fd, old_fd;
- struct stat st;
-
if (!PyArg_ParseTuple(args, "i:set_wakeup_fd", &fd))
return NULL;
-#endif
-
#ifdef WITH_THREAD
if (PyThread_get_thread_ident() != main_thread) {
PyErr_SetString(PyExc_ValueError,
@@ -522,54 +438,28 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args)
}
#endif
-#ifdef MS_WINDOWS
- if (fd != INVALID_SOCKET) {
- /* Import the _socket module to call WSAStartup() */
- mod = PyImport_ImportModuleNoBlock("_socket");
- if (mod == NULL)
- return NULL;
- Py_DECREF(mod);
-
- /* test the socket */
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR,
- (char *)&res, &res_size) != 0) {
- int err = WSAGetLastError();
- if (err == WSAENOTSOCK)
- PyErr_SetString(PyExc_ValueError, "fd is not a socket");
- else
- PyErr_SetExcFromWindowsErr(PyExc_OSError, err);
- return NULL;
- }
- }
-
- old_fd = wakeup.fd;
- wakeup.fd = fd;
-
- if (old_fd != INVALID_SOCKET)
- return PyLong_FromSocket_t(old_fd);
- else
- return PyLong_FromLong(-1);
-#else
if (fd != -1) {
- if (fstat(fd, &st) != 0) {
- PyErr_SetFromErrno(PyExc_OSError);
+ if (!_PyVerify_fd(fd)) {
+ PyErr_SetString(PyExc_ValueError, "invalid fd");
return NULL;
}
+
+ if (fstat(fd, &buf) != 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
}
old_fd = wakeup_fd;
wakeup_fd = fd;
return PyLong_FromLong(old_fd);
-#endif
}
PyDoc_STRVAR(set_wakeup_fd_doc,
"set_wakeup_fd(fd) -> fd\n\
\n\
-Sets the fd to be written to (with the signal number) when a signal\n\
+Sets the fd to be written to (with '\\0') when a signal\n\
comes in. A library can use this to wakeup select or poll.\n\
-The previous fd or -1 is returned.\n\
+The previous fd is returned.\n\
\n\
The fd must be non-blocking.");
@@ -577,17 +467,10 @@ The fd must be non-blocking.");
int
PySignal_SetWakeupFd(int fd)
{
- int old_fd;
+ int old_fd = wakeup_fd;
if (fd < 0)
fd = -1;
-
-#ifdef MS_WINDOWS
- old_fd = Py_SAFE_DOWNCAST(wakeup.fd, SOCKET_T, int);
- wakeup.fd = fd;
-#else
- old_fd = wakeup_fd;
wakeup_fd = fd;
-#endif
return old_fd;
}
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 1ad16fb..6021cd7 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -176,7 +176,7 @@
<Command>"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(PyDllName).dll</OutputFile>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
@@ -212,7 +212,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
</Link>
@@ -247,7 +247,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Debug "$(IntDir)"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
</Link>
@@ -285,7 +285,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Debug "$(IntDir)"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
</Link>
@@ -317,7 +317,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(PyDllName).dll</OutputFile>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
@@ -353,7 +353,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
<TargetMachine>MachineX64</TargetMachine>
@@ -386,7 +386,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<OutputFile>$(OutDir)$(PyDllName).dll</OutputFile>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
@@ -422,7 +422,7 @@ IF %ERRORLEVEL% NEQ 0 (
<Command>"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"</Command>
</PreLinkEvent>
<Link>
- <AdditionalDependencies>$(IntDir)getbuildinfo.o;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <AdditionalDependencies>$(IntDir)getbuildinfo.o;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libc;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<BaseAddress>0x1e000000</BaseAddress>
<TargetMachine>MachineX64</TargetMachine>