Index: configure =================================================================== --- configure (revision 61255) +++ configure (working copy) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 60787 . +# From configure.in Revision: 61238 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.61 for python 3.0. # @@ -15715,8 +15715,10 @@ -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 \ Index: configure.in =================================================================== --- configure.in (revision 61255) +++ configure.in (working copy) @@ -2273,8 +2273,8 @@ 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 \ Index: Modules/signalmodule.c =================================================================== --- Modules/signalmodule.c (revision 61255) +++ Modules/signalmodule.c (working copy) @@ -13,6 +13,7 @@ #include #include +#include #ifndef SIG_ERR #define SIG_ERR ((PyOS_sighandler_t)(-1)) @@ -93,8 +94,45 @@ static PyOS_sighandler_t old_siginthandler = SIG_DFL; +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; + + if(!(r = PyTuple_New(2))) + return NULL; + + if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_value)))) + return NULL; + + PyTuple_SET_ITEM(r, 0, v); + + if(!(v = PyFloat_FromDouble(double_from_timeval(&iv->it_interval)))) + return NULL; + + PyTuple_SET_ITEM(r, 1, v); + + return r; +} + + +static PyObject * signal_default_int_handler(PyObject *self, PyObject *args) { PyErr_SetNone(PyExc_KeyboardInterrupt); @@ -347,11 +385,76 @@ } +#ifdef HAVE_SETITIMER +static PyObject * +itimer_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; + + /* Let OS do checking on which */ + timeval_from_double(first, &new.it_value); + timeval_from_double(interval, &new.it_interval); + 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 to fire after value seconds and after that every \n\ +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 * +itimer_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", itimer_setitimer, METH_VARARGS, setitimer_doc}, +#endif +#ifdef HAVE_GETITIMER + {"getitimer", itimer_getitimer, METH_VARARGS, getitimer_doc}, +#endif {"signal", signal_signal, METH_VARARGS, signal_doc}, {"getsignal", signal_getsignal, METH_VARARGS, getsignal_doc}, {"set_wakeup_fd", signal_set_wakeup_fd, METH_VARARGS, set_wakeup_fd_doc}, @@ -374,19 +477,32 @@ 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 +755,28 @@ 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 + +#ifdef SETITIMER || GETITIMER + ItimerError = PyErr_NewException("itimer.error", NULL, NULL); + PyDict_SetItemString(d, "error", ItimerError); +#endif + if (!PyErr_Occurred()) return; Index: pyconfig.h.in =================================================================== --- pyconfig.h.in (revision 61255) +++ pyconfig.h.in (working copy) @@ -237,6 +237,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 @@ -495,6 +498,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