Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
d18ccd19
Kaydet (Commit)
d18ccd19
authored
Tem 24, 2014
tarafından
Victor Stinner
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
tets
üst
316b16de
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
278 additions
and
41 deletions
+278
-41
exceptions.rst
Doc/c-api/exceptions.rst
+10
-3
signal.rst
Doc/library/signal.rst
+5
-0
test_signal.py
Lib/test/test_signal.py
+119
-11
signalmodule.c
Modules/signalmodule.c
+136
-19
pythoncore.vcxproj
PCbuild/pythoncore.vcxproj
+8
-8
No files found.
Doc/c-api/exceptions.rst
Dosyayı görüntüle @
d18ccd19
...
...
@@ -443,13 +443,20 @@ 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 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 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 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)
...
...
Doc/library/signal.rst
Dosyayı görüntüle @
d18ccd19
...
...
@@ -308,6 +308,8 @@ 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.
...
...
@@ -318,6 +320,9 @@ 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)
...
...
Lib/test/test_signal.py
Dosyayı görüntüle @
d18ccd19
...
...
@@ -6,6 +6,7 @@ import gc
import
pickle
import
select
import
signal
import
socket
import
struct
import
subprocess
import
traceback
...
...
@@ -251,21 +252,43 @@ class WindowsSignalTests(unittest.TestCase):
class
WakeupFDTests
(
unittest
.
TestCase
):
def
test_invalid_fd
(
self
):
fd
=
support
.
make_bad_fd
()
if
sys
.
platform
==
"win32"
:
sock
=
socket
.
socket
()
fd
=
sock
.
fileno
()
sock
.
close
()
else
:
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
):
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
)
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
)
self
.
assertIs
(
signal
.
set_wakeup_fd
(
-
1
),
-
1
)
...
...
@@ -441,6 +464,90 @@ 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
):
...
...
@@ -990,6 +1097,7 @@ def test_main():
try
:
support
.
run_unittest
(
GenericTests
,
PosixTests
,
InterProcessSignalTests
,
WakeupFDTests
,
WakeupSignalTests
,
WakeupSocketSignalTests
,
SiginterruptTest
,
ItimerTest
,
WindowsSignalTests
,
PendingSignalsTests
)
finally
:
...
...
Modules/signalmodule.c
Dosyayı görüntüle @
d18ccd19
...
...
@@ -4,6 +4,9 @@
/* 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
...
...
@@ -87,7 +90,18 @@ 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
;
...
...
@@ -171,6 +185,33 @@ 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
)
{
...
...
@@ -183,26 +224,51 @@ report_wakeup_error(void *data)
errno
=
save_errno
;
return
0
;
}
#endif
static
void
trip_signal
(
int
sig_num
)
{
unsigned
char
byte
;
int
rc
=
0
;
Py_ssize_t
rc
;
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
;
while
((
rc
=
write
(
wakeup_fd
,
&
byte
,
1
))
==
-
1
&&
errno
==
EINTR
);
if
(
rc
==
-
1
)
Py_AddPendingCall
(
report_wakeup_error
,
(
void
*
)
(
Py_intptr_t
)
errno
);
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
);
}
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
...
...
@@ -426,10 +492,28 @@ signal_siginterrupt(PyObject *self, PyObject *args)
static
PyObject
*
signal_set_wakeup_fd
(
PyObject
*
self
,
PyObject
*
args
)
{
struct
stat
buf
;
#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
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
,
...
...
@@ -438,28 +522,54 @@ signal_set_wakeup_fd(PyObject *self, PyObject *args)
}
#endif
if
(
fd
!=
-
1
)
{
if
(
!
_PyVerify_fd
(
fd
))
{
PyErr_SetString
(
PyExc_ValueError
,
"invalid fd"
);
#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
;
}
}
if
(
fstat
(
fd
,
&
buf
)
!=
0
)
return
PyErr_SetFromErrno
(
PyExc_OSError
);
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
);
return
NULL
;
}
}
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
'
\\
0'
) when a signal
\n
\
Sets the fd to be written to (with
the signal number
) when a signal
\n
\
comes in. A library can use this to wakeup select or poll.
\n
\
The previous fd is returned.
\n
\
The previous fd
or -1
is returned.
\n
\
\n
\
The fd must be non-blocking."
);
...
...
@@ -467,10 +577,17 @@ The fd must be non-blocking.");
int
PySignal_SetWakeupFd
(
int
fd
)
{
int
old_fd
=
wakeup_fd
;
int
old_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
;
}
...
...
PCbuild/pythoncore.vcxproj
Dosyayı görüntüle @
d18ccd19
...
...
@@ -176,7 +176,7 @@
<Command>
"$(SolutionDir)make_buildinfo.exe" Release "$(IntDir)\"
</Command>
</PreLinkEvent>
<Link>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(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;%(AdditionalDependencies)
</AdditionalDependencies>
<AdditionalDependencies>
$(IntDir)getbuildinfo.o;
ws2_32.lib;
%(AdditionalDependencies)
</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>
libc;%(IgnoreSpecificDefaultLibraries)
</IgnoreSpecificDefaultLibraries>
<BaseAddress>
0x1e000000
</BaseAddress>
<TargetMachine>
MachineX64
</TargetMachine>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment