cvs: php4 /ext/pcntl pcntl.c php_pcntl.h php_signal.c php_signal.h test-pcntl.php
| From: | Jason Greene | Date: | Thu, 22 Aug 2002 04:20:10 +0000 |
| Subject: | cvs: php4 /ext/pcntl pcntl.c php_pcntl.h php_signal.c php_signal.h test-pcntl.php | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-13545@lists.php.net to get a copy of this message | ||
jason Thu Aug 22 00:20:10 2002 EDT
Modified files:
/php4/ext/pcntl pcntl.c php_pcntl.h php_signal.c php_signal.h
test-pcntl.php
Log:
@Made major improvents to the pcntl extension(Jason):
@ - Greatly improved performance, by switching the signal callback mechanism
@ to use ticks
@ - Implemented object signal callback ability by using array($obj, $method)
@ - Added a restart parameter to pcntl_signal, which allows you to disable
@ the default of system call restarting
Changed callback hash table to be initialized and destroyed per reqeust
(allows the ability to use request life zvals as handles)
Nuked warnings
Modified test script to adjust to new ticks backend
Some slight WS fixes
Index: php4/ext/pcntl/pcntl.c diff -u php4/ext/pcntl/pcntl.c:1.27 php4/ext/pcntl/pcntl.c:1.28 --- php4/ext/pcntl/pcntl.c:1.27 Tue Jun 4 11:51:24 2002 +++ php4/ext/pcntl/pcntl.c Thu Aug 22 00:20:10 2002 @@ -16,14 +16,15 @@ +----------------------------------------------------------------------+ */ -/* $Id: pcntl.c,v 1.27 2002/06/04 15:51:24 edink Exp $ */ +/* $Id: pcntl.c,v 1.28 2002/08/22 04:20:10 jason Exp $ */ #define PCNTL_DEBUG 0 #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 @@ 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 @@ #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 @@ } 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 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ /* Clean up */ efree(param); - efree(call_name); efree(retval); } Index: php4/ext/pcntl/php_pcntl.h diff -u php4/ext/pcntl/php_pcntl.h:1.10 php4/ext/pcntl/php_pcntl.h:1.11 --- php4/ext/pcntl/php_pcntl.h:1.10 Tue Jun 4 11:51:25 2002 +++ php4/ext/pcntl/php_pcntl.h Thu Aug 22 00:20:10 2002 @@ -16,14 +16,14 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pcntl.h,v 1.10 2002/06/04 15:51:25 edink Exp $ */ +/* $Id: php_pcntl.h,v 1.11 2002/08/22 04:20:10 jason Exp $ */ #ifndef PHP_PCNTL_H #define PHP_PCNTL_H #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_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) Index: php4/ext/pcntl/php_signal.c diff -u php4/ext/pcntl/php_signal.c:1.4 php4/ext/pcntl/php_signal.c:1.5 --- php4/ext/pcntl/php_signal.c:1.4 Thu Feb 28 03:26:35 2002 +++ php4/ext/pcntl/php_signal.c Thu Aug 22 00:20:10 2002 @@ -16,20 +16,20 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_signal.c,v 1.4 2002/02/28 08:26:35 sebastian Exp $ */ +/* $Id: php_signal.c,v 1.5 2002/08/22 04:20:10 jason Exp $ */ #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 Index: php4/ext/pcntl/php_signal.h diff -u php4/ext/pcntl/php_signal.h:1.4 php4/ext/pcntl/php_signal.h:1.5 --- php4/ext/pcntl/php_signal.h:1.4 Thu Feb 28 03:26:35 2002 +++ php4/ext/pcntl/php_signal.h Thu Aug 22 00:20:10 2002 @@ -16,13 +16,13 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_signal.h,v 1.4 2002/02/28 08:26:35 sebastian Exp $ */ +/* $Id: php_signal.h,v 1.5 2002/08/22 04:20:10 jason Exp $ */ #include <signal.h> #ifndef PHP_SIGNAL_H #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 Index: php4/ext/pcntl/test-pcntl.php diff -u php4/ext/pcntl/test-pcntl.php:1.2 php4/ext/pcntl/test-pcntl.php:1.3 --- php4/ext/pcntl/test-pcntl.php:1.2 Fri Jul 6 01:48:51 2001 +++ php4/ext/pcntl/test-pcntl.php Thu Aug 22 00:20:10 2002 @@ -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); }
Index: php4/ext/pcntl/pcntl.c diff -u php4/ext/pcntl/pcntl.c:1.27 php4/ext/pcntl/pcntl.c:1.28 --- php4/ext/pcntl/pcntl.c:1.27 Tue Jun 4 11:51:24 2002 +++ php4/ext/pcntl/pcntl.c Thu Aug 22 00:20:10 2002 @@ -16,14 +16,15 @@ +----------------------------------------------------------------------+ */ -/* $Id: pcntl.c,v 1.27 2002/06/04 15:51:24 edink Exp $ */ +/* $Id: pcntl.c,v 1.28 2002/08/22 04:20:10 jason Exp $ */ #define PCNTL_DEBUG 0 #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 @@ 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 @@ #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 @@ } 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 @@ 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 @@ } /* }}} */ -/* {{{ 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 @@ 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 @@ /* Clean up */ efree(param); - efree(call_name); efree(retval); } Index: php4/ext/pcntl/php_pcntl.h diff -u php4/ext/pcntl/php_pcntl.h:1.10 php4/ext/pcntl/php_pcntl.h:1.11 --- php4/ext/pcntl/php_pcntl.h:1.10 Tue Jun 4 11:51:25 2002 +++ php4/ext/pcntl/php_pcntl.h Thu Aug 22 00:20:10 2002 @@ -16,14 +16,14 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_pcntl.h,v 1.10 2002/06/04 15:51:25 edink Exp $ */ +/* $Id: php_pcntl.h,v 1.11 2002/08/22 04:20:10 jason Exp $ */ #ifndef PHP_PCNTL_H #define PHP_PCNTL_H #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_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) Index: php4/ext/pcntl/php_signal.c diff -u php4/ext/pcntl/php_signal.c:1.4 php4/ext/pcntl/php_signal.c:1.5 --- php4/ext/pcntl/php_signal.c:1.4 Thu Feb 28 03:26:35 2002 +++ php4/ext/pcntl/php_signal.c Thu Aug 22 00:20:10 2002 @@ -16,20 +16,20 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_signal.c,v 1.4 2002/02/28 08:26:35 sebastian Exp $ */ +/* $Id: php_signal.c,v 1.5 2002/08/22 04:20:10 jason Exp $ */ #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 Index: php4/ext/pcntl/php_signal.h diff -u php4/ext/pcntl/php_signal.h:1.4 php4/ext/pcntl/php_signal.h:1.5 --- php4/ext/pcntl/php_signal.h:1.4 Thu Feb 28 03:26:35 2002 +++ php4/ext/pcntl/php_signal.h Thu Aug 22 00:20:10 2002 @@ -16,13 +16,13 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_signal.h,v 1.4 2002/02/28 08:26:35 sebastian Exp $ */ +/* $Id: php_signal.h,v 1.5 2002/08/22 04:20:10 jason Exp $ */ #include <signal.h> #ifndef PHP_SIGNAL_H #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 Index: php4/ext/pcntl/test-pcntl.php diff -u php4/ext/pcntl/test-pcntl.php:1.2 php4/ext/pcntl/test-pcntl.php:1.3 --- php4/ext/pcntl/test-pcntl.php:1.2 Fri Jul 6 01:48:51 2001 +++ php4/ext/pcntl/test-pcntl.php Thu Aug 22 00:20:10 2002 @@ -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); }