Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Kirill Smelkov
cpython
Commits
4fa1d023
Commit
4fa1d023
authored
17 years ago
by
Martin v. Löwis
Browse files
Options
Download
Email Patches
Plain Diff
Patch #2240: Implement signal.setitimer and signal.getitimer.
parent
fc2928f9
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
313 additions
and
16 deletions
+313
-16
Doc/library/signal.rst
Doc/library/signal.rst
+60
-7
Lib/test/test_signal.py
Lib/test/test_signal.py
+85
-1
Misc/ACKS
Misc/ACKS
+1
-0
Misc/NEWS
Misc/NEWS
+5
-0
Modules/signalmodule.c
Modules/signalmodule.c
+149
-3
configure
configure
+5
-3
configure.in
configure.in
+2
-2
pyconfig.h.in
pyconfig.h.in
+6
-0
No files found.
Doc/library/signal.rst
View file @
4fa1d023
...
...
@@ -39,12 +39,13 @@ rules for working with signals and their handlers:
* Some care must be taken if both signals and threads are used in the same
program. The fundamental thing to remember in using signals and threads
simultaneously is: always perform :func:`signal` operations in the main thread
of execution. Any thread can perform an :func:`alarm`, :func:`getsignal`, or
:func:`pause`; only the main thread can set a new signal handler, and the main
thread will be the only one to receive signals (this is enforced by the Python
:mod:`signal` module, even if the underlying thread implementation supports
sending signals to individual threads). This means that signals can't be used
as a means of inter-thread communication. Use locks instead.
of execution. Any thread can perform an :func:`alarm`, :func:`getsignal`,
:func:`pause`, :func:`setitimer` or :func:`getitimer`; only the main thread
can set a new signal handler, and the main thread will be the only one to
receive signals (this is enforced by the Python :mod:`signal` module, even
if the underlying thread implementation supports sending signals to
individual threads). This means that signals can't be used as a means of
inter-thread communication. Use locks instead.
The variables defined in the :mod:`signal` module are:
...
...
@@ -78,6 +79,36 @@ The variables defined in the :mod:`signal` module are:
One more than the number of the highest signal number.
.. data:: ITIMER_REAL
Decrements interval timer in real time, and delivers SIGALRM upon expiration.
.. data:: ITIMER_VIRTUAL
Decrements interval timer only when the process is executing, and delivers
SIGVTALRM upon expiration.
.. data:: ITIMER_PROF
Decrements interval timer both when the process executes and when the
system is executing on behalf of the process. Coupled with ITIMER_VIRTUAL,
this timer is usually used to profile the time spent by the application
in user and kernel space. SIGPROF is delivered upon expiration.
The :mod:`signal` module defines one exception:
.. exception:: ItimerError
Raised to signal an error from the underlying :func:`setitimer` or
:func:`getitimer` implementation. Expect this error if an invalid
interval timer or a negative time is passed to :func:`setitimer`.
This error is a subtype of :exc:`IOError`.
The :mod:`signal` module defines the following functions:
...
...
@@ -110,6 +141,29 @@ The :mod:`signal` module defines the following functions:
:manpage:`signal(2)`.)
.. function:: setitimer(which, seconds[, interval])
Sets given itimer (one of :const:`signal.ITIMER_REAL`,
:const:`signal.ITIMER_VIRTUAL` or :const:`signal.ITIMER_PROF`) especified
by *which* to fire after *seconds* (float is accepted, different from
:func:`alarm`) and after that every *interval* seconds. The interval
timer specified by *which* can be cleared by setting seconds to zero.
The old values are returned as a tuple: (delay, interval).
Attempting to pass an invalid interval timer will cause a
:exc:`ItimerError`.
.. versionadded:: 2.6
.. function:: getitimer(which)
Returns current value of a given itimer especified by *which*.
.. versionadded:: 2.6
.. function:: set_wakeup_fd(fd)
Set the wakeup fd to *fd*. When a signal is received, a ``'\0'`` byte is
...
...
@@ -124,7 +178,6 @@ The :mod:`signal` module defines the following functions:
exception to be raised.
.. function:: siginterrupt(signalnum, flag)
Change system call restart behaviour: if *flag* is :const:`False`, system calls
...
...
This diff is collapsed.
Click to expand it.
Lib/test/test_signal.py
View file @
4fa1d023
...
...
@@ -258,9 +258,93 @@ class SiginterruptTest(unittest.TestCase):
i
=
self
.
readpipe_interrupted
(
lambda
:
signal
.
siginterrupt
(
self
.
signum
,
0
))
self
.
assertEquals
(
i
,
False
)
class
ItimerTest
(
unittest
.
TestCase
):
def
setUp
(
self
):
self
.
hndl_called
=
False
self
.
hndl_count
=
0
self
.
itimer
=
None
def
tearDown
(
self
):
if
self
.
itimer
is
not
None
:
# test_itimer_exc doesn't change this attr
# just ensure that itimer is stopped
signal
.
setitimer
(
self
.
itimer
,
0
)
def
sig_alrm
(
self
,
*
args
):
self
.
hndl_called
=
True
if
test_support
.
verbose
:
print
(
"SIGALRM handler invoked"
,
args
)
def
sig_vtalrm
(
self
,
*
args
):
self
.
hndl_called
=
True
if
self
.
hndl_count
>
3
:
# it shouldn't be here, because it should have been disabled.
raise
signal
.
ItimerError
(
"setitimer didn't disable ITIMER_VIRTUAL "
"timer."
)
elif
self
.
hndl_count
==
3
:
# disable ITIMER_VIRTUAL, this function shouldn't be called anymore
signal
.
setitimer
(
signal
.
ITIMER_VIRTUAL
,
0
)
if
test_support
.
verbose
:
print
(
"last SIGVTALRM handler call"
)
self
.
hndl_count
+=
1
if
test_support
.
verbose
:
print
(
"SIGVTALRM handler invoked"
,
args
)
def
sig_prof
(
self
,
*
args
):
self
.
hndl_called
=
True
signal
.
setitimer
(
signal
.
ITIMER_PROF
,
0
)
if
test_support
.
verbose
:
print
(
"SIGPROF handler invoked"
,
args
)
def
test_itimer_exc
(
self
):
# XXX I'm assuming -1 is an invalid itimer, but maybe some platform
# defines it ?
self
.
assertRaises
(
signal
.
ItimerError
,
signal
.
setitimer
,
-
1
,
0
)
# negative time
self
.
assertRaises
(
signal
.
ItimerError
,
signal
.
setitimer
,
signal
.
ITIMER_REAL
,
-
1
)
def
test_itimer_real
(
self
):
self
.
itimer
=
signal
.
ITIMER_REAL
signal
.
signal
(
signal
.
SIGALRM
,
self
.
sig_alrm
)
signal
.
setitimer
(
self
.
itimer
,
1.0
)
if
test_support
.
verbose
:
print
(
"
\n
call pause()..."
)
signal
.
pause
()
self
.
assertEqual
(
self
.
hndl_called
,
True
)
def
test_itimer_virtual
(
self
):
self
.
itimer
=
signal
.
ITIMER_VIRTUAL
signal
.
signal
(
signal
.
SIGVTALRM
,
self
.
sig_vtalrm
)
signal
.
setitimer
(
self
.
itimer
,
0.3
,
0.2
)
for
i
in
xrange
(
100000000
):
if
signal
.
getitimer
(
self
.
itimer
)
==
(
0.0
,
0.0
):
break
# sig_vtalrm handler stopped this itimer
# virtual itimer should be (0.0, 0.0) now
self
.
assertEquals
(
signal
.
getitimer
(
self
.
itimer
),
(
0.0
,
0.0
))
# and the handler should have been called
self
.
assertEquals
(
self
.
hndl_called
,
True
)
def
test_itimer_prof
(
self
):
self
.
itimer
=
signal
.
ITIMER_PROF
signal
.
signal
(
signal
.
SIGPROF
,
self
.
sig_prof
)
signal
.
setitimer
(
self
.
itimer
,
0.2
)
for
i
in
xrange
(
100000000
):
if
signal
.
getitimer
(
self
.
itimer
)
==
(
0.0
,
0.0
):
break
# sig_prof handler stopped this itimer
self
.
assertEqual
(
self
.
hndl_called
,
True
)
def
test_main
():
test_support
.
run_unittest
(
BasicSignalTests
,
InterProcessSignalTests
,
WakeupSignalTests
,
SiginterruptTest
)
WakeupSignalTests
,
SiginterruptTest
,
ItimerTest
)
if
__name__
==
"__main__"
:
...
...
This diff is collapsed.
Click to expand it.
Misc/ACKS
View file @
4fa1d023
...
...
@@ -528,6 +528,7 @@ Fran
Zach Pincus
Michael Piotrowski
Antoine Pitrou
Guilherme Polo
Michael Pomraning
Iustin Pop
John Popplewell
...
...
This diff is collapsed.
Click to expand it.
Misc/NEWS
View file @
4fa1d023
...
...
@@ -60,6 +60,11 @@ Core and builtins
- Issue #2143: Fix embedded readline() hang on SSL socket EOF.
Extensions Modules
------------------
- Patch #2240: Implement signal.setitimer and signal.getitimer.
Library
-------
...
...
This diff is collapsed.
Click to expand it.
Modules/signalmodule.c
View file @
4fa1d023
...
...
@@ -13,6 +13,7 @@
#include <signal.h>
#include <sys/stat.h>
#include <sys/time.h>
#ifndef SIG_ERR
#define SIG_ERR ((PyOS_sighandler_t)(-1))
...
...
@@ -93,6 +94,49 @@ static PyObject *IntHandler;
static
PyOS_sighandler_t
old_siginthandler
=
SIG_DFL
;
#ifdef HAVE_GETITIMER
static
PyObject
*
ItimerError
;
/* auxiliary functions for setitimer/getitimer */
static
void
timeval_from_double
(
double
d
,
struct
timeval
*
tv
)
{
tv
->
tv_sec
=
floor
(
d
);
tv
->
tv_usec
=
fmod
(
d
,
1
.
0
)
*
1000000
.
0
;
}
static
inline
double
double_from_timeval
(
struct
timeval
*
tv
)
{
return
tv
->
tv_sec
+
(
double
)(
tv
->
tv_usec
/
1000000
.
0
);
}
static
PyObject
*
itimer_retval
(
struct
itimerval
*
iv
)
{
PyObject
*
r
,
*
v
;
r
=
PyTuple_New
(
2
);
if
(
r
==
NULL
)
return
NULL
;
if
(
!
(
v
=
PyFloat_FromDouble
(
double_from_timeval
(
&
iv
->
it_value
))))
{
Py_DECREF
(
r
);
return
NULL
;
}
PyTuple_SET_ITEM
(
r
,
0
,
v
);
if
(
!
(
v
=
PyFloat_FromDouble
(
double_from_timeval
(
&
iv
->
it_interval
))))
{
Py_DECREF
(
r
);
return
NULL
;
}
PyTuple_SET_ITEM
(
r
,
1
,
v
);
return
r
;
}
#endif
static
PyObject
*
signal_default_int_handler
(
PyObject
*
self
,
PyObject
*
args
)
...
...
@@ -347,10 +391,76 @@ PySignal_SetWakeupFd(int fd)
}
#ifdef HAVE_SETITIMER
static
PyObject
*
signal_setitimer
(
PyObject
*
self
,
PyObject
*
args
)
{
double
first
;
double
interval
=
0
;
int
which
;
struct
itimerval
new
,
old
;
if
(
!
PyArg_ParseTuple
(
args
,
"id|d:setitimer"
,
&
which
,
&
first
,
&
interval
))
return
NULL
;
timeval_from_double
(
first
,
&
new
.
it_value
);
timeval_from_double
(
interval
,
&
new
.
it_interval
);
/* Let OS check "which" value */
if
(
setitimer
(
which
,
&
new
,
&
old
)
!=
0
)
{
PyErr_SetFromErrno
(
ItimerError
);
return
NULL
;
}
return
itimer_retval
(
&
old
);
}
PyDoc_STRVAR
(
setitimer_doc
,
"setitimer(which, seconds[, interval])
\n
\
\n
\
Sets given itimer (one of ITIMER_REAL, ITIMER_VIRTUAL
\n
\
or ITIMER_PROF) to fire after value seconds and after
\n
\
that every interval seconds.
\n
\
The itimer can be cleared by setting seconds to zero.
\n
\
\n
\
Returns old values as a tuple: (delay, interval)."
);
#endif
#ifdef HAVE_GETITIMER
static
PyObject
*
signal_getitimer
(
PyObject
*
self
,
PyObject
*
args
)
{
int
which
;
struct
itimerval
old
;
if
(
!
PyArg_ParseTuple
(
args
,
"i:getitimer"
,
&
which
))
return
NULL
;
if
(
getitimer
(
which
,
&
old
)
!=
0
)
{
PyErr_SetFromErrno
(
ItimerError
);
return
NULL
;
}
return
itimer_retval
(
&
old
);
}
PyDoc_STRVAR
(
getitimer_doc
,
"getitimer(which)
\n
\
\n
\
Returns current value of given itimer."
);
#endif
/* List of functions defined in the module */
static
PyMethodDef
signal_methods
[]
=
{
#ifdef HAVE_ALARM
{
"alarm"
,
signal_alarm
,
METH_VARARGS
,
alarm_doc
},
#endif
#ifdef HAVE_SETITIMER
{
"setitimer"
,
signal_setitimer
,
METH_VARARGS
,
setitimer_doc
},
#endif
#ifdef HAVE_GETITIMER
{
"getitimer"
,
signal_getitimer
,
METH_VARARGS
,
getitimer_doc
},
#endif
{
"signal"
,
signal_signal
,
METH_VARARGS
,
signal_doc
},
{
"getsignal"
,
signal_getsignal
,
METH_VARARGS
,
getsignal_doc
},
...
...
@@ -374,19 +484,32 @@ PyDoc_STRVAR(module_doc,
Functions:
\n
\
\n
\
alarm() -- cause SIGALRM after a specified time [Unix only]
\n
\
setitimer() -- cause a signal (described below) after a specified
\n
\
float time and the timer may restart then [Unix only]
\n
\
getitimer() -- get current value of timer [Unix only]
\n
\
signal() -- set the action for a given signal
\n
\
getsignal() -- get the signal action for a given signal
\n
\
pause() -- wait until a signal arrives [Unix only]
\n
\
default_int_handler() -- default SIGINT handler
\n
\
\n
\
Constants:
\n
\
\n
\
signal constants:
\n
\
SIG_DFL -- used to refer to the system default handler
\n
\
SIG_IGN -- used to ignore the signal
\n
\
NSIG -- number of defined signals
\n
\
\n
\
SIGINT, SIGTERM, etc. -- signal numbers
\n
\
\n
\
itimer constants:
\n
\
ITIMER_REAL -- decrements in real time, and delivers SIGALRM upon
\n
\
expiration
\n
\
ITIMER_VIRTUAL -- decrements only when the process is executing,
\n
\
and delivers SIGVTALRM upon expiration
\n
\
ITIMER_PROF -- decrements both when the process is executing and
\n
\
when the system is executing on behalf of the process.
\n
\
Coupled with ITIMER_VIRTUAL, this timer is usually
\n
\
used to profile the time spent by the application
\n
\
in user and kernel space. SIGPROF is delivered upon
\n
\
expiration.
\n
\
\n\n
\
*** IMPORTANT NOTICE ***
\n
\
A signal handler function is called with two arguments:
\n
\
the first is the signal number, the second is the interrupted stack frame."
);
...
...
@@ -639,6 +762,29 @@ initsignal(void)
PyDict_SetItemString
(
d
,
"SIGINFO"
,
x
);
Py_XDECREF
(
x
);
#endif
#ifdef ITIMER_REAL
x
=
PyLong_FromLong
(
ITIMER_REAL
);
PyDict_SetItemString
(
d
,
"ITIMER_REAL"
,
x
);
Py_DECREF
(
x
);
#endif
#ifdef ITIMER_VIRTUAL
x
=
PyLong_FromLong
(
ITIMER_VIRTUAL
);
PyDict_SetItemString
(
d
,
"ITIMER_VIRTUAL"
,
x
);
Py_DECREF
(
x
);
#endif
#ifdef ITIMER_PROF
x
=
PyLong_FromLong
(
ITIMER_PROF
);
PyDict_SetItemString
(
d
,
"ITIMER_PROF"
,
x
);
Py_DECREF
(
x
);
#endif
#if defined (HAVE_SETITIMER) || defined (HAVE_GETITIMER)
ItimerError
=
PyErr_NewException
(
"signal.ItimerError"
,
PyExc_IOError
,
NULL
);
PyDict_SetItemString
(
d
,
"ItimerError"
,
ItimerError
);
#endif
if
(
!
PyErr_Occurred
())
return
;
...
...
This diff is collapsed.
Click to expand it.
configure
View file @
4fa1d023
#! /bin/sh
# From configure.in Revision: 61
436
.
# From configure.in Revision: 61
722
.
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.61 for python 2.6.
#
...
...
@@ -15506,8 +15506,10 @@ echo "${ECHO_T}MACHDEP_OBJS" >&6; }
for ac_func in alarm bind_textdomain_codeset chown clock confstr \
ctermid execv fchmod fchown fork fpathconf ftime ftruncate \
for ac_func in alarm setitimer getitimer bind_textdomain_codeset chown \
clock confstr ctermid execv fchmod fchown fork fpathconf ftime ftruncate \
gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \
getpriority getpwent getspnam getspent getsid getwd \
kill killpg lchmod lchown lstat mkfifo mknod mktime \
...
...
This diff is collapsed.
Click to expand it.
configure.in
View file @
4fa1d023
...
...
@@ -2303,8 +2303,8 @@ fi
AC_MSG_RESULT(MACHDEP_OBJS)
# checks for library functions
AC_CHECK_FUNCS(alarm bind_textdomain_codeset chown
clock confstr
\
ctermid execv fchmod fchown fork fpathconf ftime ftruncate \
AC_CHECK_FUNCS(alarm
setitimer getitimer
bind_textdomain_codeset chown \
clock confstr
ctermid execv fchmod fchown fork fpathconf ftime ftruncate \
gai_strerror getgroups getlogin getloadavg getpeername getpgid getpid \
getpriority getpwent getspnam getspent getsid getwd \
kill killpg lchmod lchown lstat mkfifo mknod mktime \
...
...
This diff is collapsed.
Click to expand it.
pyconfig.h.in
View file @
4fa1d023
...
...
@@ -243,6 +243,9 @@
/* Define this if you have the 6-arg version of gethostbyname_r(). */
#undef HAVE_GETHOSTBYNAME_R_6_ARG
/* Define to 1 if you have the `getitimer' function. */
#undef HAVE_GETITIMER
/* Define to 1 if you have the `getloadavg' function. */
#undef HAVE_GETLOADAVG
...
...
@@ -501,6 +504,9 @@
/* Define if you have the 'setgroups' function. */
#undef HAVE_SETGROUPS
/* Define to 1 if you have the `setitimer' function. */
#undef HAVE_SETITIMER
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE
...
...
This diff is collapsed.
Click to expand it.
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