]> granicus.if.org Git - php/commitdiff
Asynchronous signal handling without TICKs.
authorDmitry Stogov <dmitry@zend.com>
Wed, 6 Jul 2016 10:11:47 +0000 (13:11 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 6 Jul 2016 10:11:47 +0000 (13:11 +0300)
Squashed commit of the following:

commit eda931df181060e202d2c664b4cba73a24afc6a1
Author: Dmitry Stogov <dmitry@zend.com>
Date:   Wed Jul 6 10:53:30 2016 +0300

    Replace pcntl.async_signals INI direcrive with pcntl_async_signals() function.

commit bfbf7dd7c2389ebada6c4464b276d9fa33fcfb60
Author: Dmitry Stogov <dmitry@zend.com>
Date:   Fri Jun 24 12:25:31 2016 +0300

    Asynchronous signal handling without TICKs.

NEWS
ext/pcntl/pcntl.c
ext/pcntl/php_pcntl.h
ext/pcntl/tests/async_signals.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 778e7c3ebcb03a53120400e3b73d77e0f3e34afa..470052bd2bc48d4624fb13c1d429e499be6ffeea 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,9 @@ PHP                                                                        NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2016, PHP 7.1.0beta1
 
+- pcntl
+  . Implemented asynchronous signal handling without TICKS. (Dmitry)
+
 07 Jul 2016, PHP 7.1.0alpha3
 
 - Core:
index ef3c7fbe3dc93d1da20f023172715ac254be5d63..5a7747acf4e1d3c8fd6c5ff4eef950c9a173aa75 100644 (file)
@@ -148,6 +148,10 @@ ZEND_END_ARG_INFO()
 ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_strerror, 0, 0, 1)
         ZEND_ARG_INFO(0, errno)
 ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_async_signals, 0, 0, 1)
+        ZEND_ARG_INFO(0, on)
+ZEND_END_ARG_INFO()
 /* }}} */
 
 const zend_function_entry pcntl_functions[] = {
@@ -183,6 +187,7 @@ const zend_function_entry pcntl_functions[] = {
 #ifdef HAVE_WCONTINUED
        PHP_FE(pcntl_wifcontinued,      arginfo_pcntl_wifcontinued)
 #endif
+       PHP_FE(pcntl_async_signals,     arginfo_pcntl_async_signals)
        PHP_FE_END
 };
 
@@ -207,8 +212,11 @@ zend_module_entry pcntl_module_entry = {
 ZEND_GET_MODULE(pcntl)
 #endif
 
+static void (*orig_interrupt_function)(zend_execute_data *execute_data);
+
 static void pcntl_signal_handler(int);
 static void pcntl_signal_dispatch();
+static void pcntl_interrupt_function(zend_execute_data *execute_data);
 
 void php_register_signal_constants(INIT_FUNC_ARGS)
 {
@@ -506,6 +514,7 @@ PHP_RINIT_FUNCTION(pcntl)
 {
        zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 0);
        PCNTL_G(head) = PCNTL_G(tail) = PCNTL_G(spares) = NULL;
+       PCNTL_G(async_signals) = 0;
        return SUCCESS;
 }
 
@@ -514,6 +523,8 @@ PHP_MINIT_FUNCTION(pcntl)
        php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU);
        php_pcntl_register_errno_constants(INIT_FUNC_ARGS_PASSTHRU);
        php_add_tick_function(pcntl_signal_dispatch, NULL);
+       orig_interrupt_function = zend_interrupt_function;
+       zend_interrupt_function = pcntl_interrupt_function;
 
        return SUCCESS;
 }
@@ -1317,6 +1328,9 @@ static void pcntl_signal_handler(int signo)
        }
        PCNTL_G(tail) = psig;
        PCNTL_G(pending_signals) = 1;
+       if (PCNTL_G(async_signals)) {
+               EG(vm_interrupt) = 1;
+       }
 }
 
 void pcntl_signal_dispatch()
@@ -1375,7 +1389,30 @@ void pcntl_signal_dispatch()
        sigprocmask(SIG_SETMASK, &old_mask, NULL);
 }
 
+/* {{{ proto bool pcntl_async_signals([bool on[)
+   Enable/disable asynchronous signal handling and return the old setting. */
+PHP_FUNCTION(pcntl_async_signals)
+{
+       zend_bool on;
 
+       if (ZEND_NUM_ARGS() == 0) {
+               RETURN_BOOL(PCNTL_G(async_signals));
+       }
+       if (zend_parse_parameters(ZEND_NUM_ARGS(), "|b", &on) == FAILURE) {
+               return;
+       }
+       RETVAL_BOOL(PCNTL_G(async_signals));
+       PCNTL_G(async_signals) = on;
+}
+/* }}} */
+
+static void pcntl_interrupt_function(zend_execute_data *execute_data)
+{
+       pcntl_signal_dispatch();
+       if (orig_interrupt_function) {
+               orig_interrupt_function(execute_data);
+       }
+}
 
 /*
  * Local variables:
index 20e7b2964a2337b4ab0c453272bb9285d72b5c8c..816bffb480f1a6ddc9eacc5dc44cbe18a03f90a4 100644 (file)
@@ -68,6 +68,7 @@ PHP_FUNCTION(pcntl_getpriority);
 #ifdef HAVE_SETPRIORITY
 PHP_FUNCTION(pcntl_setpriority);
 #endif
+PHP_FUNCTION(pcntl_async_signals);
 
 struct php_pcntl_pending_signal {
        struct php_pcntl_pending_signal *next;
@@ -80,6 +81,7 @@ ZEND_BEGIN_MODULE_GLOBALS(pcntl)
        struct php_pcntl_pending_signal *head, *tail, *spares;
        int last_error;
        volatile char pending_signals;
+       zend_bool async_signals;
 ZEND_END_MODULE_GLOBALS(pcntl)
 
 #ifdef ZTS
diff --git a/ext/pcntl/tests/async_signals.phpt b/ext/pcntl/tests/async_signals.phpt
new file mode 100644 (file)
index 0000000..b650606
--- /dev/null
@@ -0,0 +1,25 @@
+--TEST--
+Asynchronous signal handling through VM interrupts
+--SKIPIF--
+<?php
+       if (!extension_loaded("pcntl")) print "skip"; 
+       elseif (!function_exists("pcntl_signal")) print "skip pcntl_signal() not available";
+       elseif (!function_exists("posix_kill")) print "skip posix_kill() not available";
+       elseif (!function_exists("posix_getpid")) print "skip posix_getpid() not available";
+?>
+--FILE--
+<?php
+pcntl_async_signals(1);
+
+pcntl_signal(SIGTERM, function ($signo) { echo "Signal handler called!\n"; });
+
+echo "Start!\n";
+posix_kill(posix_getpid(), SIGTERM);
+$i = 0; // dummy
+echo "Done!\n";
+
+?>
+--EXPECTF--
+Start!
+Signal handler called!
+Done!