Patch pcntl_sigprocmask.diff for PCNTL related Bug #52784
Patch version 2010-09-06 16:09 UTC
Return to Bug #52784 |
Download this patch
Patch Revisions:
Developer: nick.telford@gmail.com
Index: ext/pcntl/pcntl.c
===================================================================
--- ext/pcntl/pcntl.c (revision 302771)
+++ ext/pcntl/pcntl.c (working copy)
@@ -44,6 +44,8 @@
#include <sys/resource.h>
#endif
+#include <signal.h>
+
ZEND_DECLARE_MODULE_GLOBALS(pcntl)
static PHP_GINIT_FUNCTION(pcntl);
@@ -1078,31 +1080,44 @@
{
struct php_pcntl_pending_signal *psig;
TSRMLS_FETCH();
+
+ /* block all signals temporarily while handling this signal */
+ sigset_t mask;
+ sigset_t old_mask;
+
+ /* create a mask of all signals */
+ sigfillset(&mask);
+
+ /* block all signals, storing original signal mask in old_mask */
+ sigprocmask(SIG_BLOCK, &mask, &old_mask);
psig = PCNTL_G(spares);
- if (!psig) {
- /* oops, too many signals for us to track, so we'll forget about this one */
- return;
- }
- PCNTL_G(spares) = psig->next;
+ if (psig) {
+ PCNTL_G(spares) = psig->next;
- psig->signo = signo;
- psig->next = NULL;
+ psig->signo = signo;
+ psig->next = NULL;
- /* the head check is important, as the tick handler cannot atomically clear both
- * the head and tail */
- if (PCNTL_G(head) && PCNTL_G(tail)) {
- PCNTL_G(tail)->next = psig;
- } else {
- PCNTL_G(head) = psig;
+ /* the head check is important, as the tick handler cannot atomically clear both
+ * the head and tail */
+ if (PCNTL_G(head) && PCNTL_G(tail)) {
+ PCNTL_G(tail)->next = psig;
+ } else {
+ PCNTL_G(head) = psig;
+ }
+ PCNTL_G(tail) = psig;
}
- PCNTL_G(tail) = psig;
+
+ /* done handling this signal, reset signal mask back to original state */
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
}
void pcntl_signal_dispatch()
{
zval *param, **handle, *retval;
struct php_pcntl_pending_signal *queue, *next;
+ sigset_t mask;
+ sigset_t old_mask;
TSRMLS_FETCH();
/* Bail if the queue is empty or if we are already playing the queue*/
@@ -1115,8 +1130,6 @@
queue = PCNTL_G(head);
PCNTL_G(head) = NULL; /* simple stores are atomic */
- /* Allocate */
-
while (queue) {
if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
MAKE_STD_ZVAL(retval);
@@ -1131,10 +1144,19 @@
zval_ptr_dtor(&retval);
}
+ /* create a mask of all signals */
+ sigfillset(&mask);
+
+ /* block all signals, storing original signal mask in old_mask, while we modify the linked list */
+ sigprocmask(SIG_BLOCK, &mask, &old_mask);
+
next = queue->next;
queue->next = PCNTL_G(spares);
PCNTL_G(spares) = queue;
queue = next;
+
+ /* return signal mask to previous state */
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
}
/* Re-enable queue */
|