Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
e54ddf1e
Commit
e54ddf1e
authored
May 08, 2010
by
Jean-Paul Calderone
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Skip signal handler re-installation if it is not necessary. Issue 8354.
parent
0712b565
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
87 additions
and
18 deletions
+87
-18
Lib/test/test_signal.py
Lib/test/test_signal.py
+75
-18
Misc/NEWS
Misc/NEWS
+3
-0
Modules/signalmodule.c
Modules/signalmodule.c
+5
-0
Python/pythonrun.c
Python/pythonrun.c
+4
-0
No files found.
Lib/test/test_signal.py
View file @
e54ddf1e
...
...
@@ -255,48 +255,105 @@ class WakeupSignalTests(unittest.TestCase):
class
SiginterruptTest
(
unittest
.
TestCase
):
signum
=
signal
.
SIGUSR1
def
readpipe_interrupted
(
self
,
cb
):
def
setUp
(
self
):
"""Install a no-op signal handler that can be set to allow
interrupts or not, and arrange for the original signal handler to be
re-installed when the test is finished.
"""
oldhandler
=
signal
.
signal
(
self
.
signum
,
lambda
x
,
y
:
None
)
self
.
addCleanup
(
signal
.
signal
,
self
.
signum
,
oldhandler
)
def
readpipe_interrupted
(
self
):
"""Perform a read during which a signal will arrive. Return True if the
read is interrupted by the signal and raises an exception. Return False
if it returns normally.
"""
# Create a pipe that can be used for the read. Also clean it up
# when the test is over, since nothing else will (but see below for
# the write end).
r
,
w
=
os
.
pipe
()
self
.
addCleanup
(
os
.
close
,
r
)
# Create another process which can send a signal to this one to try
# to interrupt the read.
ppid
=
os
.
getpid
()
pid
=
os
.
fork
()
oldhandler
=
signal
.
signal
(
self
.
signum
,
lambda
x
,
y
:
None
)
cb
()
if
pid
==
0
:
# child code: sleep, kill, sleep. and then exit,
# which closes the pipe from which the parent process reads
if
pid
==
0
:
# Child code: sleep to give the parent enough time to enter the
# read() call (there's a race here, but it's really tricky to
# eliminate it); then signal the parent process. Also, sleep
# again to make it likely that the signal is delivered to the
# parent process before the child exits. If the child exits
# first, the write end of the pipe will be closed and the test
# is invalid.
try
:
time
.
sleep
(
0.2
)
os
.
kill
(
ppid
,
self
.
signum
)
time
.
sleep
(
0.2
)
finally
:
# No matter what, just exit as fast as possible now.
exit_subprocess
()
try
:
else
:
# Parent code.
# Make sure the child is eventually reaped, else it'll be a
# zombie for the rest of the test suite run.
self
.
addCleanup
(
os
.
waitpid
,
pid
,
0
)
# Close the write end of the pipe. The child has a copy, so
# it's not really closed until the child exits. We need it to
# close when the child exits so that in the non-interrupt case
# the read eventually completes, otherwise we could just close
# it *after* the test.
os
.
close
(
w
)
# Try the read and report whether it is interrupted or not to
# the caller.
try
:
d
=
os
.
read
(
r
,
1
)
d
=
os
.
read
(
r
,
1
)
return
False
except
OSError
,
err
:
if
err
.
errno
!=
errno
.
EINTR
:
raise
return
True
finally
:
signal
.
signal
(
self
.
signum
,
oldhandler
)
os
.
waitpid
(
pid
,
0
)
def
test_without_siginterrupt
(
self
):
i
=
self
.
readpipe_interrupted
(
lambda
:
None
)
self
.
assertEquals
(
i
,
True
)
"""If a signal handler is installed and siginterrupt is not called
at all, when that signal arrives, it interrupts a syscall that's in
progress.
"""
i
=
self
.
readpipe_interrupted
()
self
.
assertTrue
(
i
)
# Arrival of the signal shouldn't have changed anything.
i
=
self
.
readpipe_interrupted
()
self
.
assertTrue
(
i
)
def
test_siginterrupt_on
(
self
):
i
=
self
.
readpipe_interrupted
(
lambda
:
signal
.
siginterrupt
(
self
.
signum
,
1
))
self
.
assertEquals
(
i
,
True
)
"""If a signal handler is installed and siginterrupt is called with
a true value for the second argument, when that signal arrives, it
interrupts a syscall that's in progress.
"""
signal
.
siginterrupt
(
self
.
signum
,
1
)
i
=
self
.
readpipe_interrupted
()
self
.
assertTrue
(
i
)
# Arrival of the signal shouldn't have changed anything.
i
=
self
.
readpipe_interrupted
()
self
.
assertTrue
(
i
)
def
test_siginterrupt_off
(
self
):
i
=
self
.
readpipe_interrupted
(
lambda
:
signal
.
siginterrupt
(
self
.
signum
,
0
))
self
.
assertEquals
(
i
,
False
)
"""If a signal handler is installed and siginterrupt is called with
a false value for the second argument, when that signal arrives, it
does not interrupt a syscall that's in progress.
"""
signal
.
siginterrupt
(
self
.
signum
,
0
)
i
=
self
.
readpipe_interrupted
()
self
.
assertFalse
(
i
)
# Arrival of the signal shouldn't have changed anything.
i
=
self
.
readpipe_interrupted
()
self
.
assertFalse
(
i
)
class
ItimerTest
(
unittest
.
TestCase
):
def
setUp
(
self
):
...
...
Misc/NEWS
View file @
e54ddf1e
...
...
@@ -96,6 +96,9 @@ Library
- Issue #4687: Fix accuracy of garbage collection runtimes displayed with
gc.DEBUG_STATS.
- Issue #8354: The siginterrupt setting is now preserved for all signals,
not just SIGCHLD.
- Issue #7192: webbrowser.get("firefox") now wors on Mac OS X, as does
webbrowser.get("safari").
...
...
Modules/signalmodule.c
View file @
e54ddf1e
...
...
@@ -198,7 +198,12 @@ signal_handler(int sig_num)
return
;
}
#endif
#ifndef HAVE_SIGACTION
/* If the handler was not set up with sigaction, reinstall it. See
* Python/pythonrun.c for the implementation of PyOS_setsig which
* makes this true. See also issue8354. */
PyOS_setsig
(
sig_num
,
signal_handler
);
#endif
}
...
...
Python/pythonrun.c
View file @
e54ddf1e
...
...
@@ -1862,6 +1862,10 @@ PyOS_sighandler_t
PyOS_setsig
(
int
sig
,
PyOS_sighandler_t
handler
)
{
#ifdef HAVE_SIGACTION
/* Some code in Modules/signalmodule.c depends on sigaction() being
* used here if HAVE_SIGACTION is defined. Fix that if this code
* changes to invalidate that assumption.
*/
struct
sigaction
context
,
ocontext
;
context
.
sa_handler
=
handler
;
sigemptyset
(
&
context
.
sa_mask
);
...
...
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