diff options
-rwxr-xr-x | ext/pcntl/pcntl.c | 185 | ||||
-rw-r--r-- | ext/pcntl/php_pcntl.h | 10 | ||||
-rw-r--r-- | ext/pcntl/php_signal.c | 6 | ||||
-rw-r--r-- | ext/pcntl/php_signal.h | 2 | ||||
-rwxr-xr-x | ext/pcntl/test-pcntl.php | 48 |
5 files changed, 74 insertions, 177 deletions
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 2af78df9fa..d09e7aac1a 100755 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -22,8 +22,9 @@ #if PCNTL_DEBUG #define DEBUG_OUT printf("DEBUG: ");printf +#define IF_DEBUG(z) z #else -#define DEBUG_OUT +#define IF_DEBUG(z) #endif #ifdef HAVE_CONFIG_H @@ -37,9 +38,6 @@ ZEND_DECLARE_MODULE_GLOBALS(pcntl) -static int le_pcntl; -static int pcntl_zend_extension_active; - function_entry pcntl_functions[] = { PHP_FE(pcntl_fork, NULL) PHP_FE(pcntl_waitpid, second_arg_force_ref) @@ -61,8 +59,8 @@ zend_module_entry pcntl_module_entry = { pcntl_functions, PHP_MINIT(pcntl), PHP_MSHUTDOWN(pcntl), - NULL, - NULL, + PHP_RINIT(pcntl), + PHP_RSHUTDOWN(pcntl), PHP_MINFO(pcntl), NO_VERSION_YET, STANDARD_MODULE_PROPERTIES @@ -70,32 +68,8 @@ zend_module_entry pcntl_module_entry = { #ifdef COMPILE_DL_PCNTL ZEND_GET_MODULE(pcntl) -#define PCNTL_ZEND_EXT ZEND_DLEXPORT -#else -#define PCNTL_ZEND_EXT #endif -PCNTL_ZEND_EXT zend_extension pcntl_extension_entry = { - "pcntl", - "1.0", - "Jason Greene", - "http://www.php.net", - "2001", - pcntl_zend_extension_startup, - pcntl_zend_extension_shutdown, - pcntl_zend_extension_activate, - pcntl_zend_extension_deactivate, - NULL, - NULL, - pcntl_zend_extension_statement_handler, - NULL, - NULL, - NULL, - NULL, - NULL -}; - - void php_register_signal_constants(INIT_FUNC_ARGS) { @@ -159,9 +133,7 @@ void php_register_signal_constants(INIT_FUNC_ARGS) } static void php_pcntl_init_globals(zend_pcntl_globals *pcntl_globals) -{ - zend_hash_init(&pcntl_globals->php_signal_table, 16, NULL, NULL, 1); - +{ /* Just in case ... */ memset(&pcntl_globals->php_signal_queue,0,sizeof(pcntl_globals->php_signal_queue)); @@ -170,30 +142,32 @@ static void php_pcntl_init_globals(zend_pcntl_globals *pcntl_globals) pcntl_globals->processing_signal_queue = 0; } -static void php_pcntl_shutdown_globals(zend_pcntl_globals *pcntl_globals) +PHP_RINIT_FUNCTION(pcntl) { - zend_hash_destroy(&pcntl_globals->php_signal_table); - zend_llist_destroy(&pcntl_globals->php_signal_queue); + zend_hash_init(&PCNTL_G(php_signal_table), 16, NULL, ZVAL_PTR_DTOR, 1); + return SUCCESS; } PHP_MINIT_FUNCTION(pcntl) { php_register_signal_constants(INIT_FUNC_ARGS_PASSTHRU); - ZEND_INIT_MODULE_GLOBALS(pcntl, php_pcntl_init_globals, php_pcntl_shutdown_globals); - if (zend_register_extension(&pcntl_extension_entry, 0)==FAILURE) - return FAILURE; + ZEND_INIT_MODULE_GLOBALS(pcntl, php_pcntl_init_globals, NULL); + php_add_tick_function(pcntl_tick_handler); + return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(pcntl) { - zend_hash_destroy(&PCNTL_G(php_signal_table)); zend_llist_destroy(&PCNTL_G(php_signal_queue)); return SUCCESS; } - - +PHP_RSHUTDOWN_FUNCTION(pcntl) +{ + zend_hash_destroy(&PCNTL_G(php_signal_table)); + return SUCCESS; +} PHP_MINFO_FUNCTION(pcntl) { @@ -475,141 +449,69 @@ PHP_FUNCTION(pcntl_exec) } /* }}} */ -/* {{{ proto bool pcntl_signal(long signo, mixed handle) +/* {{{ proto bool pcntl_signal(long signo, mixed handle, [bool restart_syscalls]) Assigns a system signal handler to a PHP function */ PHP_FUNCTION(pcntl_signal) { - zval **signo, **handle; + zval *handle, **dest_handle = NULL; char *func_name; + long signo; + zend_bool restart_syscalls = 1; - if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &signo, &handle) == FAILURE) { - WRONG_PARAM_COUNT; + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz|b", &signo, &handle, &restart_syscalls) == FAILURE) { + return; } - convert_to_long_ex(signo); - /* Special long value case for SIG_DFL and SIG_IGN */ - if (Z_TYPE_PP(handle)==IS_LONG) { - if (Z_LVAL_PP(handle)!= (long) SIG_DFL && Z_LVAL_PP(handle) != (long) SIG_IGN) { + if (Z_TYPE_P(handle)==IS_LONG) { + if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) { php_error(E_WARNING, "Invalid value for handle argument specifEied in %s", get_active_function_name(TSRMLS_C)); } - if (php_signal(Z_LVAL_PP(signo), (Sigfunc *) Z_LVAL_PP(handle))==SIG_ERR) { + if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) { php_error(E_WARNING, "Error assigning singal in %s", get_active_function_name(TSRMLS_C)); RETURN_FALSE; } RETURN_TRUE; } - if (Z_TYPE_PP(handle) != IS_STRING) { - php_error(E_WARNING, "Invalid type specified for handle argument in %s", get_active_function_name(TSRMLS_C)); - RETURN_FALSE; - } - - convert_to_string_ex(handle); /* Just in case */ - if (!zend_is_callable(*handle, 0, &func_name)) { + if (!zend_is_callable(handle, 0, &func_name)) { php_error(E_WARNING, "%s: %s is not a callable function name error", get_active_function_name(TSRMLS_C), func_name); efree(func_name); RETURN_FALSE; } efree(func_name); - - /* Add the function name to our signal table */ - zend_hash_index_update(&PCNTL_G(php_signal_table), Z_LVAL_PP(signo), Z_STRVAL_PP(handle), (Z_STRLEN_PP(handle) + 1) * sizeof(char), NULL); - if (php_signal(Z_LVAL_PP(signo), pcntl_signal_handler)==SIG_ERR) { - php_error(E_WARNING, "Error assigning singal in %s", get_active_function_name(TSRMLS_C)); - RETURN_FALSE; + /* Add the function name to our signal table */ + zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle); + if (dest_handle) zval_add_ref(dest_handle); + + if (php_signal(signo, pcntl_signal_handler, (int) restart_syscalls) == SIG_ERR) { + php_error(E_WARNING, "Error assigning singal in %s", get_active_function_name(TSRMLS_C)); + RETURN_FALSE; } RETURN_TRUE; } /* }}} */ -/* Note Old */ -static void old_pcntl_signal_handler(int signo) -{ - char *func_name; - zval *param, *call_name, *retval; - TSRMLS_FETCH(); - - DEBUG_OUT("Caught signal: %d\n", signo); - if (zend_hash_index_find(&PCNTL_G(php_signal_table), (long) signo, (void *) &func_name)==FAILURE) { - DEBUG_OUT("Signl handler not fount"); - return; - } - /* DEBUG_OUT("Signal handler found, Calling %s\n", func_name); */ - MAKE_STD_ZVAL(param); - MAKE_STD_ZVAL(call_name); - MAKE_STD_ZVAL(retval); - ZVAL_LONG(param, signo); - ZVAL_STRING(call_name, func_name, 1); - - /* Call php singal handler - Note that we do not report errors, and we ignore the return value */ - call_user_function(EG(function_table), NULL, call_name, retval, 1, ¶m TSRMLS_CC); - - zval_dtor(call_name); - efree(call_name); - efree(param); - efree(retval); - - return; -} - /* Our custom signal handler that calls the appropriate php_function */ static void pcntl_signal_handler(int signo) { long signal_num = signo; TSRMLS_FETCH(); - DEBUG_OUT("Caught signo %d\n", signo); - if (! PCNTL_G(processing_signal_queue) && pcntl_zend_extension_active ) { + IF_DEBUG(DEBUG_OUT("Caught signo %d\n", signo)); + if (! PCNTL_G(processing_signal_queue)) { zend_llist_add_element(&PCNTL_G(php_signal_queue), &signal_num); PCNTL_G(signal_queue_ready) = 1; - DEBUG_OUT("Added queue entry\n"); + IF_DEBUG(DEBUG_OUT("Added queue entry\n")); } return; } -/* Pcntl Zend Extension Hooks */ - -int pcntl_zend_extension_startup(zend_extension *extension) -{ - TSRMLS_FETCH(); - - DEBUG_OUT("Statup Called\n"); - pcntl_zend_extension_active = 1; - CG(extended_info) = 1; - return SUCCESS; -} - -void pcntl_zend_extension_shutdown(zend_extension *extension) -{ - DEBUG_OUT("Shutdown Called\n"); - return; -} - -void pcntl_zend_extension_activate(void) -{ - TSRMLS_FETCH(); - - DEBUG_OUT("Activate Called\n"); - pcntl_zend_extension_active = 1; - CG(extended_info) = 1; - return; -} - -void pcntl_zend_extension_deactivate(void) -{ - DEBUG_OUT("Deactivate Called\n"); - pcntl_zend_extension_active = 0; - return; -} - -/* Custom hook to ensure signals only get called at a safe poing in Zend's execute process */ -void pcntl_zend_extension_statement_handler(zend_op_array *op_array) +void pcntl_tick_handler() { zend_llist_element *element; - zval *param, *call_name, *retval; - char *func_name; + zval *param, **handle, *retval; TSRMLS_FETCH(); /* Bail if the queue is empty or if we are already playing the queue*/ @@ -624,26 +526,24 @@ void pcntl_zend_extension_statement_handler(zend_op_array *op_array) return; } - /* Disable queue so this function is not infinate */ + /* Prevent reentrant handler calls */ PCNTL_G(processing_signal_queue) = 1; /* Allocate */ MAKE_STD_ZVAL(param); - MAKE_STD_ZVAL(call_name); MAKE_STD_ZVAL(retval); /* Traverse through our signal queue and call the appropriate php functions */ for (element = (&PCNTL_G(php_signal_queue))->head; element; element = element->next) { long *signal_num = (long *)&element->data; - if (zend_hash_index_find(&PCNTL_G(php_signal_table), *signal_num, (void *) &func_name)==FAILURE) { + if (zend_hash_index_find(&PCNTL_G(php_signal_table), *signal_num, (void **) &handle)==FAILURE) { continue; } ZVAL_LONG(param, *signal_num); - ZVAL_STRING(call_name, func_name, 0); - /* Call php singal handler - Note that we do not report errors, and we ignore the return value */ - call_user_function(EG(function_table), NULL, call_name, retval, 1, ¶m TSRMLS_CC); + /* Call php singal handler - Note that we do not report errors, and we ignore the eturn value */ + call_user_function(EG(function_table), NULL, *handle, retval, 1, ¶m TSRMLS_CC); } /* Clear */ zend_llist_clean(&PCNTL_G(php_signal_queue)); @@ -653,7 +553,6 @@ void pcntl_zend_extension_statement_handler(zend_op_array *op_array) /* Clean up */ efree(param); - efree(call_name); efree(retval); } diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h index f06cbcddf2..b982d33102 100644 --- a/ext/pcntl/php_pcntl.h +++ b/ext/pcntl/php_pcntl.h @@ -23,7 +23,7 @@ #include <sys/wait.h> #include "php_signal.h" -#include "zend_extensions.h" +#include "php_ticks.h" extern zend_module_entry pcntl_module_entry; #define phpext_pcntl_ptr &pcntl_module_entry @@ -52,13 +52,7 @@ PHP_FUNCTION(pcntl_signal); PHP_FUNCTION(pcntl_exec); static void pcntl_signal_handler(int); - -/* Zend extension prototypes */ -int pcntl_zend_extension_startup(zend_extension *extension); -void pcntl_zend_extension_shutdown(zend_extension *extension); -void pcntl_zend_extension_activate(void); -void pcntl_zend_extension_deactivate(void); -void pcntl_zend_extension_statement_handler(zend_op_array *op_array); +static void pcntl_tick_handler(); ZEND_BEGIN_MODULE_GLOBALS(pcntl) diff --git a/ext/pcntl/php_signal.c b/ext/pcntl/php_signal.c index 41172a988b..840eb46b44 100644 --- a/ext/pcntl/php_signal.c +++ b/ext/pcntl/php_signal.c @@ -20,16 +20,16 @@ #include "php_signal.h" -/* php_signal using sigaction is taken verbatim from Advanced Programing +/* php_signal using sigaction is derrived from Advanced Programing * in the Unix Environment by W. Richard Stevens p 298. */ -Sigfunc *php_signal(int signo, Sigfunc *func) +Sigfunc *php_signal(int signo, Sigfunc *func, int restart) { struct sigaction act,oact; act.sa_handler = func; sigemptyset(&act.sa_mask); act.sa_flags = 0; - if (signo == SIGALRM) { + if (signo == SIGALRM || (! restart)) { #ifdef SA_INTERRUPT act.sa_flags |= SA_INTERRUPT; /* SunOS */ #endif diff --git a/ext/pcntl/php_signal.h b/ext/pcntl/php_signal.h index 63baa4c3a3..e4657a68af 100644 --- a/ext/pcntl/php_signal.h +++ b/ext/pcntl/php_signal.h @@ -23,6 +23,6 @@ #define PHP_SIGNAL_H typedef void Sigfunc(int); -Sigfunc *php_signal(int signo, Sigfunc *func); +Sigfunc *php_signal(int signo, Sigfunc *func, int restart); #endif diff --git a/ext/pcntl/test-pcntl.php b/ext/pcntl/test-pcntl.php index 41334ba814..6b3ee5649e 100755 --- a/ext/pcntl/test-pcntl.php +++ b/ext/pcntl/test-pcntl.php @@ -1,35 +1,39 @@ -#!/opt/devel/php4/php -q +#!../../php -q <? + +declare(ticks=1); + function alarm_handle($signal){ if ($signal==SIGALRM) print "Caught SIGALRM!!!\n"; } + function usr1_handle($signal){ - if ($signal==SIGUSR1) print "Caught SIGUSR1!!!\n"; + if ($signal==SIGUSR1) print "Caught SIGUSR1!!!\n"; } print "This test will demonstrate a fork followed by ipc via signals.\n"; $pid=pcntl_fork(); if ($pid==0) { - pcntl_signal(SIGUSR1, "usr1_handle"); - pcntl_signal(SIGALRM, "alarm_handle"); - print "Child: Waiting for alarm.....\n"; - sleep(100); - print "Child: Waiting for usr1......\n"; - sleep(100); - print "Child: Resetting Alarm handler to Ignore....\n"; - pcntl_signal(SIGALRM, SIG_IGN); - sleep(10); - print "Done\n"; + pcntl_signal(SIGUSR1, "usr1_handle"); + pcntl_signal(SIGALRM, "alarm_handle"); + print "Child: Waiting for alarm.....\n"; + sleep(100); + print "Child: Waiting for usr1......\n"; + sleep(100); + print "Child: Resetting Alarm handler to Ignore....\n"; + pcntl_signal(SIGALRM, SIG_IGN); + sleep(10); + print "Done\n"; } else { - print "Parent: Waiting 10 seconds....\n"; - sleep(10); - print "Parent: Sending SIGALRM to Child\n"; - posix_kill($pid,SIGALRM); - sleep(1); - print "Parent: Senging SIGUSR1 to Child\n"; - posix_kill($pid,SIGUSR1); - sleep(1); - print "Parent: Sending SIGALRM to Child\n"; - pcntl_waitpid($pid, &$status, $options); + print "Parent: Waiting 10 seconds....\n"; + sleep(10); + print "Parent: Sending SIGALRM to Child\n"; + posix_kill($pid,SIGALRM); + sleep(1); + print "Parent: Senging SIGUSR1 to Child\n"; + posix_kill($pid,SIGUSR1); + sleep(1); + print "Parent: Sending SIGALRM to Child\n"; + pcntl_waitpid($pid, &$status, $options); } |