1 /*--- posix_signal.c -----------------------------------------------------------
2 This is nothing but a forward port from older python code by Lance Ellinghaus,
3 Guido van Rossum & al., reformatted and put back together by Sylvain Fourmanoit <syfou@users.sourceforge.net>
4 for recent (2.2.0 final and newer) python implementations.
6 The ability to temporarily delay signals delivery is a very usefull feature -
7 not all C functions are reentrant (in fact, only a few need to be 'safe'
8 according to the POSIX 1003.1-2003 list), so being able to create critical
9 code sections is a must. Although I am convinced Python's developpers
10 had good reasons, I do not know myself why 'sigprocmask' and associated
11 functions support was dropped from the signal module on systems which
12 implemented them... Since I needed them in my blissful ignorance,
13 here they are, alive and kicking. :-)
15 ------------------------------------------------------------------------------*/
22 #ifdef HAVE_SIGPROCMASK
24 _posix_signal_list_to_sigset(PyObject
* seq
, sigset_t
* set
, char* mesg
)
28 seq
= PySequence_Fast(seq
, mesg
);
32 len
= PySequence_Fast_GET_SIZE(seq
);
36 for (i
= 0; i
< len
; i
++) {
37 val
= PyInt_AsLong(PySequence_Fast_GET_ITEM(seq
, i
));
38 if (val
== -1 && PyErr_Occurred()) {
42 if (sigaddset(set
, val
) < 0) {
44 PyErr_SetFromErrno(PyExc_ValueError
);
54 _posix_signal_sigset_to_list(sigset_t
* set
)
64 for (i
= 1; i
< NSIG
; i
++) {
65 if (sigismember(set
, i
)) {
66 ob
= PyInt_FromLong(i
);
71 PyList_Append(ret
, ob
);
80 posix_signal_sigprocmask(PyObject
* self
, PyObject
* args
)
83 sigset_t newset
, oldset
;
86 if (!PyArg_ParseTuple(args
, "iO", &how
, &seq
))
89 if (_posix_signal_list_to_sigset(seq
, &newset
,
90 "sigprocmask requires a sequence") < 0)
93 if (sigprocmask(how
, &newset
, &oldset
) < 0) {
94 return PyErr_SetFromErrno(PyExc_ValueError
);
97 if (PyErr_CheckSignals())
100 return _posix_signal_sigset_to_list(&oldset
);
103 PyDoc_STRVAR(sigprocmask_doc
,
104 "sigprocmask(how, sigset) -> sigset\n\
106 Change the list of currently blocked signals. The parameter how should be\n\
107 one of SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK and sigset should be a\n\
108 sequence of signal numbers. The behaviour of the call depends on the value\n\
112 The set of blocked signals is the union of the current set and the\n\
115 The signals in sigset are removed from the current set of blocked\n\
116 signals. It is legal to attempt to unblock a signal which is not\n\
119 The set of blocked signals is set to the argument set.\n\
121 A list contating the numbers of the previously blocked signals is returned.");
124 posix_signal_sigpending(PyObject
* self
)
128 if (sigpending(&set
) < 0) {
129 return PyErr_SetFromErrno(PyExc_ValueError
);
132 return _posix_signal_sigset_to_list(&set
);
135 PyDoc_STRVAR(sigpending_doc
,
136 "sigpending() -> sigset\n\
138 Return the set of pending signals, i.e. a list containing the numbers of\n\
139 those signals that have been raised while blocked.");
142 posix_signal_sigsuspend(PyObject
* self
, PyObject
* arg
)
146 if (_posix_signal_list_to_sigset(arg
, &set
,
147 "sigsuspend requires a sequence") < 0)
150 Py_BEGIN_ALLOW_THREADS
154 if (PyErr_CheckSignals())
161 PyDoc_STRVAR(sigsuspend_doc
,
162 "sigsuspend(sigset) -> None\n\
164 Temporarily replace the signal mask with sigset (which should be a sequence\n\
165 of signal numbers) and suspend the process until a signal is received.");
169 #ifdef HAVE_SIGPROCMASK
170 PyDoc_STRVAR(module_doc
,
171 "This module supersets the core signal module to enable POSIX signal functions\n\
172 on platforms supporting them. Core `signal' module functions and constants\n\
173 are imported verbatim in posix_signal namespace.\n\
177 sigprocmask() -- Change the list of currently blocked signals\n\
178 sigpending() -- Allow the examination of pending signals\n\
179 sigsuspend() -- Temporarily replace the signal mask and then suspend\n\
180 the process until a signal is received\n\
184 SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK -- See sigprocmask help below\n\
186 --- signal module documentation ----\n\
190 PyDoc_STRVAR(module_doc
,
191 "This module supersets the core signal module to enable POSIX signal functions\n\
192 on platforms supporting them. Core `signal' module functions and constants\n\
193 are imported verbatim in posix_signal namespace.\n\
195 WARNING: support for reliable POSIX signals was not detected on your system,\n\
196 and therefore not compiled in. In that state of affair, this module is only \n\
197 a placeholder for your core signal module.\n\
199 --- signal module documentation ----\n\
203 /* List of functions defined in the module */
204 static PyMethodDef posix_signal_methods
[] = {
205 #ifdef HAVE_SIGPROCMASK
206 {"sigprocmask", posix_signal_sigprocmask
, METH_VARARGS
, sigprocmask_doc
},
207 {"sigpending", (PyCFunction
)posix_signal_sigpending
, METH_VARARGS
, sigpending_doc
},
208 {"sigsuspend", posix_signal_sigsuspend
, METH_VARARGS
, sigsuspend_doc
},
210 { NULL
, NULL
, 0, NULL
}
214 initposix_signal(void)
216 const char * KEYS
[] = { "__doc__", "__name__" , NULL
};
218 char * key_str
, * doc_str
, * new_str
;
219 PyObject
* m
, * mDoc
, *d
,
220 * pName
, * pModule
, * pDict
,
223 m
= Py_InitModule3("posix_signal", posix_signal_methods
, module_doc
);
224 d
= PyModule_GetDict(m
);
226 x
= PyInt_FromLong(SIG_BLOCK
);
227 PyDict_SetItemString(d
, "SIG_BLOCK", x
);
229 x
= PyInt_FromLong(SIG_UNBLOCK
);
230 PyDict_SetItemString(d
, "SIG_UNBLOCK", x
);
232 x
= PyInt_FromLong(SIG_SETMASK
);
233 PyDict_SetItemString(d
, "SIG_SETMASK", x
);
236 /* The chunk of code below roughly perfoms python equivalent of:
237 'from signal import *' inside what would be a pure python posix_signal
239 pName
=PyString_FromString("signal");
240 if ((pModule
=PyImport_Import((pName
=PyString_FromString("signal"))))) {
241 pDict
=PyModule_GetDict(pModule
);
242 while (PyDict_Next(pDict
, &pos
, &key
, &value
))
243 /* Import all values from keys that are strings */
244 if (PyString_Check(key
)) {
245 key_str
=PyString_AsString(key
);
247 if (strncmp(key_str
,KEYS
[i
],strlen(KEYS
[i
]))==0)
250 /* This needs python 2.2 and up */
251 PyModule_AddObject(m
,key_str
,value
);
254 /* Append signal module documentation */
255 if ((mDoc
=PyDict_GetItemString(d
,KEYS
[0]))) {
256 doc_str
=PyString_AsString(mDoc
);
257 key_str
=PyString_AsString(value
);
259 malloc(sizeof(char)*(strlen(doc_str
)+strlen(key_str
))+1))) {
260 strcpy(new_str
,doc_str
);
261 strcat(new_str
,key_str
);
262 if(PyDict_SetItemString(d
,KEYS
[0],
263 (mDoc
=PyString_FromString(new_str
)))<0) {