Created
September 24, 2014 18:14
-
-
Save auroraeosrose/b17c03728ccda9162d2b to your computer and use it in GitHub Desktop.
That pcntl patch I've been sitting on
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Index: config.w32 | |
=================================================================== | |
--- config.w32 (revision 0) | |
+++ config.w32 (revision 0) | |
@@ -0,0 +1,8 @@ | |
+// $Id: config.w32 264053 2008-08-01 21:20:08Z pajoye $ | |
+// vim:ft=javascript | |
+ | |
+ARG_ENABLE("pcntl", "process control support", "no"); | |
+ | |
+if (PHP_PCNTL != "no") { | |
+ EXTENSION("pcntl", "pcntl.c pcntl_win.c php_signal.c"); | |
+} | |
Index: pcntl.c | |
=================================================================== | |
--- pcntl.c (revision 290360) | |
+++ pcntl.c (working copy) | |
@@ -17,16 +17,6 @@ | |
*/ | |
/* $Id$ */ | |
- | |
-#define PCNTL_DEBUG 0 | |
- | |
-#if PCNTL_DEBUG | |
-#define DEBUG_OUT printf("DEBUG: ");printf | |
-#define IF_DEBUG(z) z | |
-#else | |
-#define IF_DEBUG(z) | |
-#endif | |
- | |
#ifdef HAVE_CONFIG_H | |
#include "config.h" | |
#endif | |
@@ -34,11 +24,15 @@ | |
#include "php.h" | |
#include "php_ini.h" | |
#include "ext/standard/info.h" | |
+ | |
+#ifdef _MSC_VER | |
+# include "pcntl_win.h" | |
+#endif | |
#include "php_pcntl.h" | |
#include "php_signal.h" | |
#include "php_ticks.h" | |
-#if HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3 | |
+#if !defined(_MSC_VER) && (HAVE_GETPRIORITY || HAVE_SETPRIORITY || HAVE_WAIT3) | |
#include <sys/wait.h> | |
#include <sys/time.h> | |
#include <sys/resource.h> | |
@@ -48,9 +42,6 @@ | |
static PHP_GINIT_FUNCTION(pcntl); | |
/* {{{ arginfo */ | |
-ZEND_BEGIN_ARG_INFO(arginfo_pcntl_void, 0) | |
-ZEND_END_ARG_INFO() | |
- | |
ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_waitpid, 0, 0, 2) | |
ZEND_ARG_INFO(0, pid) | |
ZEND_ARG_INFO(1, status) | |
@@ -120,6 +111,17 @@ | |
ZEND_ARG_INFO(0, seconds) | |
ZEND_END_ARG_INFO() | |
+ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_spawn, 0, 0, 1) | |
+ ZEND_ARG_INFO(0, path) | |
+ ZEND_ARG_INFO(0, mode) | |
+ ZEND_ARG_INFO(0, args) | |
+ ZEND_ARG_INFO(0, envs) | |
+ZEND_END_ARG_INFO() | |
+ | |
+ZEND_BEGIN_ARG_INFO(arginfo_pcntl_raise, 0) | |
+ ZEND_ARG_INFO(0, signal) | |
+ZEND_END_ARG_INFO() | |
+ | |
#ifdef HAVE_GETPRIORITY | |
ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_getpriority, 0, 0, 0) | |
ZEND_ARG_INFO(0, pid) | |
@@ -137,19 +139,24 @@ | |
/* }}} */ | |
const zend_function_entry pcntl_functions[] = { | |
- PHP_FE(pcntl_fork, arginfo_pcntl_void) | |
- PHP_FE(pcntl_waitpid, arginfo_pcntl_waitpid) | |
- PHP_FE(pcntl_wait, arginfo_pcntl_wait) | |
- PHP_FE(pcntl_signal, arginfo_pcntl_signal) | |
- PHP_FE(pcntl_signal_dispatch, arginfo_pcntl_void) | |
- PHP_FE(pcntl_wifexited, arginfo_pcntl_wifexited) | |
- PHP_FE(pcntl_wifstopped, arginfo_pcntl_wifstopped) | |
- PHP_FE(pcntl_wifsignaled, arginfo_pcntl_wifsignaled) | |
- PHP_FE(pcntl_wexitstatus, arginfo_pcntl_wifexitstatus) | |
- PHP_FE(pcntl_wtermsig, arginfo_pcntl_wtermsig) | |
- PHP_FE(pcntl_wstopsig, arginfo_pcntl_wstopsig) | |
- PHP_FE(pcntl_exec, arginfo_pcntl_exec) | |
- PHP_FE(pcntl_alarm, arginfo_pcntl_alarm) | |
+#ifdef fork | |
+ PHP_FE(pcntl_fork, NULL) | |
+#endif | |
+ PHP_FE(pcntl_waitpid, arginfo_pcntl_waitpid) | |
+ PHP_FE(pcntl_wait, arginfo_pcntl_wait) | |
+ PHP_FE(pcntl_signal, arginfo_pcntl_signal) | |
+ PHP_FE(pcntl_signal_dispatch, NULL) | |
+ PHP_FE(pcntl_wifexited, arginfo_pcntl_wifexited) | |
+ PHP_FE(pcntl_wifstopped, arginfo_pcntl_wifstopped) | |
+ PHP_FE(pcntl_wifsignaled, arginfo_pcntl_wifsignaled) | |
+ PHP_FE(pcntl_wexitstatus, arginfo_pcntl_wifexitstatus) | |
+ PHP_FE(pcntl_wtermsig, arginfo_pcntl_wtermsig) | |
+ PHP_FE(pcntl_wstopsig, arginfo_pcntl_wstopsig) | |
+ PHP_FE(pcntl_exec, arginfo_pcntl_exec) | |
+ //PHP_FE(pcntl_alarm, arginfo_pcntl_alarm) | |
+ PHP_FE(pcntl_spawn, arginfo_pcntl_spawn) | |
+ PHP_FE(pcntl_raise, arginfo_pcntl_raise) | |
+ PHP_FE(pcntl_executable, NULL) | |
#ifdef HAVE_GETPRIORITY | |
PHP_FE(pcntl_getpriority, arginfo_pcntl_getpriority) | |
#endif | |
@@ -171,15 +178,15 @@ | |
"pcntl", | |
pcntl_functions, | |
PHP_MINIT(pcntl), | |
- PHP_MSHUTDOWN(pcntl), | |
+ NULL, /* MSHUTDOWN */ | |
PHP_RINIT(pcntl), | |
PHP_RSHUTDOWN(pcntl), | |
PHP_MINFO(pcntl), | |
NO_VERSION_YET, | |
PHP_MODULE_GLOBALS(pcntl), | |
PHP_GINIT(pcntl), | |
+ NULL, /* GSHUTDOWN */ | |
NULL, | |
- NULL, | |
STANDARD_MODULE_PROPERTIES_EX | |
}; | |
@@ -192,7 +199,6 @@ | |
void php_register_signal_constants(INIT_FUNC_ARGS) | |
{ | |
- | |
/* Wait Constants */ | |
#ifdef WNOHANG | |
REGISTER_LONG_CONSTANT("WNOHANG", (long) WNOHANG, CONST_CS | CONST_PERSISTENT); | |
@@ -200,28 +206,53 @@ | |
#ifdef WUNTRACED | |
REGISTER_LONG_CONSTANT("WUNTRACED", (long) WUNTRACED, CONST_CS | CONST_PERSISTENT); | |
#endif | |
+#ifdef WCONTINUED | |
+ REGISTER_LONG_CONSTANT("WCONTINUED", (long) WCONTINUED, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+ /* Spawn Constants */ | |
+ REGISTER_LONG_CONSTANT("SPAWN_NOWAIT", 0, CONST_CS | CONST_PERSISTENT); | |
+ REGISTER_LONG_CONSTANT("SPAWN_WAIT", 1, CONST_CS | CONST_PERSISTENT); | |
+ | |
/* Signal Constants */ | |
REGISTER_LONG_CONSTANT("SIG_IGN", (long) SIG_IGN, CONST_CS | CONST_PERSISTENT); | |
REGISTER_LONG_CONSTANT("SIG_DFL", (long) SIG_DFL, CONST_CS | CONST_PERSISTENT); | |
REGISTER_LONG_CONSTANT("SIG_ERR", (long) SIG_ERR, CONST_CS | CONST_PERSISTENT); | |
+#ifdef SIGHUP | |
REGISTER_LONG_CONSTANT("SIGHUP", (long) SIGHUP, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
REGISTER_LONG_CONSTANT("SIGINT", (long) SIGINT, CONST_CS | CONST_PERSISTENT); | |
+#ifdef SIGQUIT | |
REGISTER_LONG_CONSTANT("SIGQUIT", (long) SIGQUIT, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
REGISTER_LONG_CONSTANT("SIGILL", (long) SIGILL, CONST_CS | CONST_PERSISTENT); | |
+#ifdef SIGTRAP | |
REGISTER_LONG_CONSTANT("SIGTRAP", (long) SIGTRAP, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
REGISTER_LONG_CONSTANT("SIGABRT", (long) SIGABRT, CONST_CS | CONST_PERSISTENT); | |
#ifdef SIGIOT | |
REGISTER_LONG_CONSTANT("SIGIOT", (long) SIGIOT, CONST_CS | CONST_PERSISTENT); | |
#endif | |
+#ifdef SIGBUS | |
REGISTER_LONG_CONSTANT("SIGBUS", (long) SIGBUS, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
REGISTER_LONG_CONSTANT("SIGFPE", (long) SIGFPE, CONST_CS | CONST_PERSISTENT); | |
+#ifdef SIGKILL | |
REGISTER_LONG_CONSTANT("SIGKILL", (long) SIGKILL, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGUSR1 | |
REGISTER_LONG_CONSTANT("SIGUSR1", (long) SIGUSR1, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
REGISTER_LONG_CONSTANT("SIGSEGV", (long) SIGSEGV, CONST_CS | CONST_PERSISTENT); | |
+#ifdef SIGUSR2 | |
REGISTER_LONG_CONSTANT("SIGUSR2", (long) SIGUSR2, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGPIPE | |
REGISTER_LONG_CONSTANT("SIGPIPE", (long) SIGPIPE, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGALRM | |
REGISTER_LONG_CONSTANT("SIGALRM", (long) SIGALRM, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
REGISTER_LONG_CONSTANT("SIGTERM", (long) SIGTERM, CONST_CS | CONST_PERSISTENT); | |
#ifdef SIGSTKFLT | |
REGISTER_LONG_CONSTANT("SIGSTKFLT",(long) SIGSTKFLT, CONST_CS | CONST_PERSISTENT); | |
@@ -232,21 +263,45 @@ | |
#ifdef SIGCHLD | |
REGISTER_LONG_CONSTANT("SIGCHLD", (long) SIGCHLD, CONST_CS | CONST_PERSISTENT); | |
#endif | |
+#ifdef SIGCONT | |
REGISTER_LONG_CONSTANT("SIGCONT", (long) SIGCONT, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGSTOP | |
REGISTER_LONG_CONSTANT("SIGSTOP", (long) SIGSTOP, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGTSTP | |
REGISTER_LONG_CONSTANT("SIGTSTP", (long) SIGTSTP, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGTTIN | |
REGISTER_LONG_CONSTANT("SIGTTIN", (long) SIGTTIN, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGTTOU | |
REGISTER_LONG_CONSTANT("SIGTTOU", (long) SIGTTOU, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGURG | |
REGISTER_LONG_CONSTANT("SIGURG", (long) SIGURG , CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGXCPU | |
REGISTER_LONG_CONSTANT("SIGXCPU", (long) SIGXCPU, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGXFSZ | |
REGISTER_LONG_CONSTANT("SIGXFSZ", (long) SIGXFSZ, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGVTALRM | |
REGISTER_LONG_CONSTANT("SIGVTALRM",(long) SIGVTALRM, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGPROF | |
REGISTER_LONG_CONSTANT("SIGPROF", (long) SIGPROF, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
+#ifdef SIGWINCH | |
REGISTER_LONG_CONSTANT("SIGWINCH", (long) SIGWINCH, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
#ifdef SIGPOLL | |
REGISTER_LONG_CONSTANT("SIGPOLL", (long) SIGPOLL, CONST_CS | CONST_PERSISTENT); | |
#endif | |
+#ifdef SIGIO | |
REGISTER_LONG_CONSTANT("SIGIO", (long) SIGIO, CONST_CS | CONST_PERSISTENT); | |
+#endif | |
#ifdef SIGPWR | |
REGISTER_LONG_CONSTANT("SIGPWR", (long) SIGPWR, CONST_CS | CONST_PERSISTENT); | |
#endif | |
@@ -403,9 +458,9 @@ | |
#ifdef BUS_OBJERR | |
REGISTER_LONG_CONSTANT("BUS_OBJERR", BUS_OBJERR, CONST_CS | CONST_PERSISTENT); | |
#endif | |
-#endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */ | |
- /* }}} */ | |
+#endif /* HAVE_SIGWAITINFO && HAVE_SIGTIMEDWAIT */ | |
} | |
+/* }}} */ | |
static PHP_GINIT_FUNCTION(pcntl) | |
{ | |
@@ -427,11 +482,6 @@ | |
return SUCCESS; | |
} | |
-PHP_MSHUTDOWN_FUNCTION(pcntl) | |
-{ | |
- return SUCCESS; | |
-} | |
- | |
PHP_RSHUTDOWN_FUNCTION(pcntl) | |
{ | |
struct php_pcntl_pending_signal *sig; | |
@@ -451,7 +501,6 @@ | |
} | |
return SUCCESS; | |
} | |
- | |
PHP_MINFO_FUNCTION(pcntl) | |
{ | |
php_info_print_table_start(); | |
@@ -459,8 +508,10 @@ | |
php_info_print_table_end(); | |
} | |
+#ifdef fork | |
/* {{{ proto int pcntl_fork(void) | |
- Forks the currently running process following the same behavior as the UNIX fork() system call*/ | |
+ Forks the currently running process following the same behavior as the UNIX fork() system call | |
+ not available on windows */ | |
PHP_FUNCTION(pcntl_fork) | |
{ | |
pid_t id; | |
@@ -473,6 +524,7 @@ | |
RETURN_LONG((long) id); | |
} | |
/* }}} */ | |
+#endif | |
/* {{{ proto int pcntl_alarm(int seconds) | |
Set an alarm clock for delivery of a signal*/ | |
@@ -512,7 +564,7 @@ | |
/* }}} */ | |
/* {{{ proto int pcntl_wait(int &status) | |
- Waits on or returns the status of a forked child as defined by the waitpid() system call */ | |
+ Waits on or returns the status of a forked child as defined by the wait() system call */ | |
PHP_FUNCTION(pcntl_wait) | |
{ | |
long options = 0; | |
@@ -778,6 +830,7 @@ | |
if (Z_TYPE_P(handle)==IS_LONG) { | |
if (Z_LVAL_P(handle)!= (long) SIG_DFL && Z_LVAL_P(handle) != (long) SIG_IGN) { | |
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for handle argument specified"); | |
+ RETURN_FALSE; | |
} | |
if (php_signal(signo, (Sigfunc *) Z_LVAL_P(handle), (int) restart_syscalls) == SIG_ERR) { | |
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal"); | |
@@ -793,7 +846,7 @@ | |
} | |
efree(func_name); | |
- /* Add the function name to our signal table */ | |
+ /* 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); | |
@@ -809,11 +862,29 @@ | |
Dispatch signals to signal handlers */ | |
PHP_FUNCTION(pcntl_signal_dispatch) | |
{ | |
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { | |
+ return; | |
+ } | |
+ | |
pcntl_signal_dispatch(); | |
RETURN_TRUE; | |
} | |
/* }}} */ | |
+/* {{{ proto bool pcntl_raise() | |
+ calls raise, allowing signals to be sent without posix extension or kill */ | |
+PHP_FUNCTION(pcntl_raise) | |
+{ | |
+ long signo; | |
+ | |
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &signo) == FAILURE) { | |
+ return; | |
+ } | |
+ | |
+ RETURN_LONG(raise(signo)); | |
+} | |
+/* }}} */ | |
+ | |
#ifdef HAVE_SIGPROCMASK | |
/* {{{ proto bool pcntl_sigprocmask(int how, array set[, array &oldset]) | |
Examine and change blocked signals */ | |
@@ -1073,6 +1144,227 @@ | |
/* }}} */ | |
#endif | |
+/* {{{ proto int pcntl_spawn(string path [, int mode, [array args [, array envs]]]) | |
+ implemented as fork + exec for most systems | |
+ roughly equivalent to fork + exec, this uses win32 api calls on windows */ | |
+PHP_FUNCTION(pcntl_spawn) | |
+{ | |
+ zval *args = NULL, *envs = NULL; | |
+ zval **element; | |
+ HashTable *args_hash, *envs_hash; | |
+ int argc = 0, argi = 0; | |
+ int envc = 0, envi = 0; | |
+ int return_val = 0; | |
+ char **argv = NULL, **envp = NULL; | |
+ char **current_arg, **pair; | |
+ int pair_length; | |
+ char *key; | |
+ uint key_length; | |
+ char *path; | |
+ int path_len; | |
+ ulong key_num; | |
+ long mode = _P_NOWAIT; | |
+ intptr_t pid; | |
+ | |
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|laa", &path, &path_len, &mode, &args, &envs) == FAILURE) { | |
+ return; | |
+ } | |
+ | |
+ if (ZEND_NUM_ARGS() > 2) { | |
+ /* Build argumnent list */ | |
+ args_hash = HASH_OF(args); | |
+ argc = zend_hash_num_elements(args_hash); | |
+ | |
+ argv = safe_emalloc((argc + 2), sizeof(char *), 0); | |
+ *argv = path; | |
+ for ( zend_hash_internal_pointer_reset(args_hash), current_arg = argv+1; | |
+ (argi < argc && (zend_hash_get_current_data(args_hash, (void **) &element) == SUCCESS)); | |
+ (argi++, current_arg++, zend_hash_move_forward(args_hash)) ) { | |
+ | |
+ convert_to_string_ex(element); | |
+ *current_arg = Z_STRVAL_PP(element); | |
+ } | |
+ *(current_arg) = NULL; | |
+ } else { | |
+ argv = emalloc(2 * sizeof(char *)); | |
+ *argv = path; | |
+ *(argv+1) = NULL; | |
+ } | |
+ | |
+ if ( ZEND_NUM_ARGS() == 4 ) { | |
+ /* Build environment pair list */ | |
+ envs_hash = HASH_OF(envs); | |
+ envc = zend_hash_num_elements(envs_hash); | |
+ | |
+ envp = safe_emalloc((envc + 1), sizeof(char *), 0); | |
+ for ( zend_hash_internal_pointer_reset(envs_hash), pair = envp; | |
+ (envi < envc && (zend_hash_get_current_data(envs_hash, (void **) &element) == SUCCESS)); | |
+ (envi++, pair++, zend_hash_move_forward(envs_hash)) ) { | |
+ switch (return_val = zend_hash_get_current_key_ex(envs_hash, &key, &key_length, &key_num, 0, NULL)) { | |
+ case HASH_KEY_IS_LONG: | |
+ key = emalloc(101); | |
+ snprintf(key, 100, "%ld", key_num); | |
+ key_length = strlen(key); | |
+ break; | |
+ case HASH_KEY_NON_EXISTANT: | |
+ pair--; | |
+ continue; | |
+ } | |
+ | |
+ convert_to_string_ex(element); | |
+ | |
+ /* Length of element + equal sign + length of key + null */ | |
+ pair_length = Z_STRLEN_PP(element) + key_length + 2; | |
+ *pair = emalloc(pair_length); | |
+ strlcpy(*pair, key, key_length); | |
+ strlcat(*pair, "=", pair_length); | |
+ strlcat(*pair, Z_STRVAL_PP(element), pair_length); | |
+ | |
+ /* Cleanup */ | |
+ if (return_val == HASH_KEY_IS_LONG) efree(key); | |
+ } | |
+ *(pair) = NULL; | |
+#ifdef _MSC_VER | |
+ /* Verify our modes, wait and nowait are supported */ | |
+ if (mode) { | |
+ mode = _P_WAIT; | |
+ } else { | |
+ mode = _P_NOWAIT; | |
+ } | |
+ /* spawn - NOTICE, with wait mode you will get back EXIT STATUS, with nowait you get PID */ | |
+ pid = spawnve(mode, path, argv, envp); | |
+ | |
+ if (pid < 0) { | |
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno)); | |
+ } | |
+#else | |
+ int status; | |
+ | |
+ /* Do the fork */ | |
+ switch(pid = fork()){ | |
+ case -1: | |
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d", errno); | |
+ case 0 : | |
+ /* This is the child, do the exec */ | |
+ if (execve(path, argv, envp) == -1) { | |
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno)); | |
+ } | |
+ default: | |
+ /* If wait is on, then wait and assign the return status, otherwise ignore */ | |
+ if (mode) { | |
+ waitpid((pid_t) pid, &status, NULL); | |
+ pid = status; | |
+ } | |
+ } | |
+#endif | |
+ /* Cleanup */ | |
+ for (pair = envp; *pair != NULL; pair++) efree(*pair); | |
+ efree(envp); | |
+ } else { | |
+#ifdef _MSC_VER | |
+ /* Verify our modes, wait and nowait are supported */ | |
+ if (mode) { | |
+ mode = _P_WAIT; | |
+ } else { | |
+ mode = _P_NOWAIT; | |
+ } | |
+ /* spawn - NOTICE, with wait mode you will get back EXIT STATUS, with nowait you get PID */ | |
+ pid = spawnv(mode, path, argv); | |
+ | |
+ if (pid < 0) { | |
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno)); | |
+ } | |
+ | |
+ if (!mode) { | |
+ pid = GetProcessId(pid); | |
+ } | |
+#else | |
+ int status; | |
+ | |
+ /* Do the fork */ | |
+ switch(pid = fork()){ | |
+ case -1: | |
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error %d", errno); | |
+ case 0 : | |
+ /* This is the child, do the exec */ | |
+ if (execv(path, argv) == -1) { | |
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error has occured: (errno %d) %s", errno, strerror(errno)); | |
+ } | |
+ default: | |
+ /* If wait is on, then wait and assign the return status, otherwise ignore */ | |
+ if (mode) { | |
+ waitpid((pid_t) pid, &status, NULL); | |
+ pid = status; | |
+ } | |
+ } | |
+#endif | |
+ } | |
+ | |
+ efree(argv); | |
+ | |
+ RETURN_LONG(pid); | |
+} | |
+/* }}} */ | |
+ | |
+/* {{{ proto string pcntl_executable() | |
+ returns the current binary executable - may NOT give you what you expect with some SAPIS */ | |
+PHP_FUNCTION(pcntl_executable) | |
+{ | |
+ char *binary_location; | |
+ | |
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "") == FAILURE) { | |
+ return; | |
+ } | |
+ | |
+#ifdef PHP_WIN32 | |
+ binary_location = (char *) emalloc(MAXPATHLEN); | |
+ if (GetModuleFileName(0, binary_location, MAXPATHLEN) == 0) { | |
+ efree(binary_location); | |
+ binary_location = NULL; | |
+ } | |
+#else | |
+ if (sapi_module.executable_location) { | |
+ binary_location = (char *)emalloc(MAXPATHLEN); | |
+ if (!strchr(sapi_module.executable_location, '/')) { | |
+ char *envpath, *path; | |
+ int found = 0; | |
+ | |
+ if ((envpath = getenv("PATH")) != NULL) { | |
+ char *search_dir, search_path[MAXPATHLEN]; | |
+ char *last; | |
+ | |
+ path = estrdup(envpath); | |
+ search_dir = php_strtok_r(path, ":", &last); | |
+ | |
+ while (search_dir) { | |
+ snprintf(search_path, MAXPATHLEN, "%s/%s", search_dir, sapi_module.executable_location); | |
+ if (VCWD_REALPATH(search_path, binary_location) && !VCWD_ACCESS(binary_location, X_OK)) { | |
+ found = 1; | |
+ break; | |
+ } | |
+ search_dir = php_strtok_r(NULL, ":", &last); | |
+ } | |
+ efree(path); | |
+ } | |
+ if (!found) { | |
+ efree(binary_location); | |
+ binary_location = NULL; | |
+ } | |
+ } else if (!VCWD_REALPATH(sapi_module.executable_location, binary_location) || VCWD_ACCESS(binary_location, X_OK)) { | |
+ efree(binary_location); | |
+ binary_location = NULL; | |
+ } | |
+ } else { | |
+ binary_location = NULL; | |
+ } | |
+#endif | |
+ RETVAL_STRING(binary_location, 1); | |
+ if (binary_location) { | |
+ efree(binary_location); | |
+ } | |
+} | |
+/* }}} */ | |
+ | |
/* Our custom signal handler that calls the appropriate php_function */ | |
static void pcntl_signal_handler(int signo) | |
{ | |
@@ -1105,7 +1397,7 @@ | |
struct php_pcntl_pending_signal *queue, *next; | |
TSRMLS_FETCH(); | |
- /* Bail if the queue is empty or if we are already playing the queue*/ | |
+ /* Bail if the queue is empty or if we are already playing the queue */ | |
if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) | |
return; | |
@@ -1129,6 +1421,11 @@ | |
call_user_function(EG(function_table), NULL, *handle, retval, 1, ¶m TSRMLS_CC); | |
zval_ptr_dtor(¶m); | |
zval_ptr_dtor(&retval); | |
+ | |
+#ifdef _MSC_VER | |
+ /* Windows is using straight signal calls, reput the item back in */ | |
+ php_signal(queue->signo, (Sigfunc *) Z_LVAL_PP(handle), 0); | |
+#endif | |
} | |
next = queue->next; | |
@@ -1141,8 +1438,6 @@ | |
PCNTL_G(processing_signal_queue) = 0; | |
} | |
- | |
- | |
/* | |
* Local variables: | |
* tab-width: 4 | |
Index: pcntl_win.c | |
=================================================================== | |
--- pcntl_win.c (revision 0) | |
+++ pcntl_win.c (revision 0) | |
@@ -0,0 +1,181 @@ | |
+/* | |
+ +----------------------------------------------------------------------+ | |
+ | PHP Version 5 | | |
+ +----------------------------------------------------------------------+ | |
+ | Copyright (c) 1997-2009 The PHP Group | | |
+ +----------------------------------------------------------------------+ | |
+ | This source file is subject to version 3.01 of the PHP license, | | |
+ | that is bundled with this package in the file LICENSE, and is | | |
+ | available through the world-wide-web at the following url: | | |
+ | http://www.php.net/license/3_01.txt | | |
+ | If you did not receive a copy of the PHP license and are unable to | | |
+ | obtain it through the world-wide-web, please send a note to | | |
+ | [email protected] so we can mail you a copy immediately. | | |
+ +----------------------------------------------------------------------+ | |
+ | Author: Jason Greene <[email protected]> | | |
+ +----------------------------------------------------------------------+ | |
+ */ | |
+ | |
+/* $Id$ */ | |
+ | |
+#include "php.h" | |
+#include "pcntl_win.h" | |
+ | |
+/* Implementation of waitpid - only supports WNOHANG for options */ | |
+pid_t waitpid (pid_t pid, int *stat_loc, int options) { | |
+ DWORD timeout; | |
+ | |
+ if (options == WNOHANG) { | |
+ timeout = 0; | |
+ } else { | |
+ timeout = INFINITE; | |
+ } | |
+ if (WaitForSingleObject((HANDLE) pid, timeout) == WAIT_OBJECT_0) { | |
+ pid = _cwait(stat_loc, pid, 0); | |
+ return pid; | |
+ } | |
+ return 0; | |
+} | |
+ | |
+/* Implementation of wait - only supports processes created via the pcntl_spawn method */ | |
+pid_t wait (int *stat_loc) { | |
+ // TODO: make spawn store the process handles on nowait | |
+ // put process handle hashtable in globals | |
+ // make waitpid and wait remove process handles | |
+ // similiar to perl's handling of the matter ;) | |
+ return 0; | |
+} | |
+ | |
+/* Implementation of alarm using timers */ | |
+unsigned int alarm(unsigned int seconds) { | |
+} | |
+ | |
+/* Implementation of setpriority using SetPriorityClass */ | |
+int setpriority(int which, int who, int prio) { | |
+ HANDLE process; | |
+ zend_bool close_handle = 0; | |
+ DWORD dwFlag = NORMAL_PRIORITY_CLASS; | |
+ BOOL success; | |
+ | |
+ /* On windows, which can only be 0 */ | |
+ if (which != 0) { | |
+ errno = EINVAL; /* Invalid which value */ | |
+ return -1; | |
+ } | |
+ | |
+ /* If who is 0, get the current process handle */ | |
+ if (who == 0) { | |
+ process = GetCurrentProcess(); | |
+ } else { | |
+ /* Take the pid provided and open a process handle to use */ | |
+ process = OpenProcess(PROCESS_SET_INFORMATION, FALSE, who); | |
+ if (!process) { | |
+ errno = ESRCH; /* Invalid identifier */ | |
+ return -1; | |
+ } else { | |
+ close_handle = 1; | |
+ } | |
+ } | |
+ | |
+ /* Translate priorities into windows priority constants | |
+ range is guessed at -15 to 15 - 0 is included in normal */ | |
+ /* anything less then -10 is idle */ | |
+ if (prio < -10) { | |
+ dwFlag = IDLE_PRIORITY_CLASS; | |
+ /* -10 to -5 is below normal */ | |
+ } else if (prio < -5 && prio > -11) { | |
+ dwFlag = BELOW_NORMAL_PRIORITY_CLASS; | |
+ /* -5 to 0 is normal */ | |
+ } else if (prio > -6 && prio < 1) { | |
+ dwFlag = NORMAL_PRIORITY_CLASS; | |
+ /* 1 to 5 is above normal */ | |
+ } else if (prio > 0 && prio < 6) { | |
+ dwFlag = ABOVE_NORMAL_PRIORITY_CLASS; | |
+ /* 5 to 10 is high */ | |
+ } else if (prio > 5 && prio < 11) { | |
+ dwFlag = HIGH_PRIORITY_CLASS; | |
+ /* anything above 10 is realtime */ | |
+ } else if (prio > 10) { | |
+ dwFlag = REALTIME_PRIORITY_CLASS; | |
+ } | |
+ | |
+ /* do the setpriority call */ | |
+ success = SetPriorityClass(process, dwFlag); | |
+ | |
+ /* close any handles */ | |
+ if (close_handle) { | |
+ CloseHandle(process); | |
+ } | |
+ | |
+ /* return values are -1 for an error or zero for worked */ | |
+ if (success == 0) { | |
+ /* windows uses 0 for fail */ | |
+ errno = GetLastError(); | |
+ return -1; | |
+ } else { | |
+ return 0; | |
+ } | |
+} | |
+ | |
+/* Implementation of getpriority using GetPriorityClass */ | |
+int getpriority(int which, int who) { | |
+ HANDLE process; | |
+ zend_bool close_handle = 0; | |
+ DWORD value; | |
+ | |
+ /* On windows, which can only be 0 */ | |
+ if (which != 0) { | |
+ errno = EINVAL; /* Invalid which value */ | |
+ return -1; | |
+ } | |
+ | |
+ /* If who is 0, get the current process handle */ | |
+ if (who == 0) { | |
+ process = GetCurrentProcess(); | |
+ } else { | |
+ /* Take the pid provided and open a process handle to use */ | |
+ process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, who); | |
+ if (!process) { | |
+ errno = ESRCH; /* Invalid identifier */ | |
+ return -1; | |
+ } else { | |
+ close_handle = 1; | |
+ } | |
+ } | |
+ | |
+ /* do the getpriority call */ | |
+ value = GetPriorityClass(process); | |
+ | |
+ /* close any handles */ | |
+ if (close_handle) { | |
+ CloseHandle(process); | |
+ } | |
+ | |
+ /* Translate the windows priority constants into simple ints | |
+ range is guessed at -15 to 15 - 0 is included in normal */ | |
+ /* anything less then -10 is idle */ | |
+ switch(value) { | |
+ case IDLE_PRIORITY_CLASS: | |
+ return -11; | |
+ case BELOW_NORMAL_PRIORITY_CLASS: | |
+ return -6; | |
+ case NORMAL_PRIORITY_CLASS: | |
+ return 0; | |
+ case ABOVE_NORMAL_PRIORITY_CLASS: | |
+ return 4; | |
+ case HIGH_PRIORITY_CLASS: | |
+ return 9; | |
+ case REALTIME_PRIORITY_CLASS: | |
+ return 15; | |
+ default: | |
+ return 1; | |
+ } | |
+} | |
+ | |
+/* | |
+ * Local variables: | |
+ * tab-width: 4 | |
+ * c-basic-offset: 4 | |
+ * indent-tabs-mode: t | |
+ * End: | |
+ */ | |
Property changes on: pcntl_win.c | |
___________________________________________________________________ | |
Added: svn:keywords | |
+ Id | |
Index: pcntl_win.h | |
=================================================================== | |
--- pcntl_win.h (revision 0) | |
+++ pcntl_win.h (revision 0) | |
@@ -0,0 +1,54 @@ | |
+/* | |
+ +----------------------------------------------------------------------+ | |
+ | PHP Version 5 | | |
+ +----------------------------------------------------------------------+ | |
+ | Copyright (c) 1997-2009 The PHP Group | | |
+ +----------------------------------------------------------------------+ | |
+ | This source file is subject to version 3.01 of the PHP license, | | |
+ | that is bundled with this package in the file LICENSE, and is | | |
+ | available through the world-wide-web at the following url: | | |
+ | http://www.php.net/license/3_01.txt | | |
+ | If you did not receive a copy of the PHP license and are unable to | | |
+ | obtain it through the world-wide-web, please send a note to | | |
+ | [email protected] so we can mail you a copy immediately. | | |
+ +----------------------------------------------------------------------+ | |
+ | Author: Jason Greene <[email protected]> | | |
+ +----------------------------------------------------------------------+ | |
+*/ | |
+ | |
+/* $Id$ */ | |
+ | |
+#ifndef PHP_PCNTL_WIN_H | |
+#define PHP_PCNTL_WIN_H | |
+ | |
+#define HAVE_GETPRIORITY 1 | |
+#define HAVE_SETPRIORITY 1 | |
+ | |
+/* | |
+ * MSVC is missing these macros | |
+ */ | |
+#define WIFEXITED(stat) (((*((int *) &(stat))) & 0xff) == 0) | |
+#define WEXITSTATUS(stat) (((*((int *) &(stat))) >> 8) & 0xff) | |
+#define WIFSIGNALED(stat) (((*((int *) &(stat)))) && ((*((int *) &(stat))) == ((*((int *) &(stat))) & 0x00ff))) | |
+#define WTERMSIG(stat) ((*((int *) &(stat))) & 0x7f) | |
+#define WIFSTOPPED(stat) (((*((int *) &(stat))) & 0xff) == 0177) | |
+#define WSTOPSIG(stat) (((*((int *) &(stat))) >> 8) & 0xff) | |
+ | |
+#define WNOHANG 1 | |
+#define WUNTRACED 2 | |
+ | |
+#define PRIO_PROCESS 0 | |
+#define PRIO_PGRP 1 | |
+#define PRIO_USER 2 | |
+ | |
+#ifndef intptr_t | |
+ typedef INT_PTR intptr_t; | |
+#endif | |
+ | |
+pid_t waitpid (pid_t pid, int *stat_loc, int options); | |
+pid_t wait (int *stat_loc); | |
+unsigned int alarm(unsigned int seconds); | |
+int setpriority(int which, int who, int prio); | |
+int getpriority(int which, int who); | |
+ | |
+#endif | |
Property changes on: pcntl_win.h | |
___________________________________________________________________ | |
Added: svn:keywords | |
+ Id | |
Index: php_pcntl.h | |
=================================================================== | |
--- php_pcntl.h (revision 290360) | |
+++ php_pcntl.h (working copy) | |
@@ -25,7 +25,6 @@ | |
#define phpext_pcntl_ptr &pcntl_module_entry | |
PHP_MINIT_FUNCTION(pcntl); | |
-PHP_MSHUTDOWN_FUNCTION(pcntl); | |
PHP_RINIT_FUNCTION(pcntl); | |
PHP_RSHUTDOWN_FUNCTION(pcntl); | |
PHP_MINFO_FUNCTION(pcntl); | |
@@ -42,6 +41,7 @@ | |
PHP_FUNCTION(pcntl_wstopsig); | |
PHP_FUNCTION(pcntl_signal); | |
PHP_FUNCTION(pcntl_signal_dispatch); | |
+PHP_FUNCTION(pcntl_raise); | |
#ifdef HAVE_SIGPROCMASK | |
PHP_FUNCTION(pcntl_sigprocmask); | |
#endif | |
@@ -56,6 +56,8 @@ | |
#ifdef HAVE_SETPRIORITY | |
PHP_FUNCTION(pcntl_setpriority); | |
#endif | |
+PHP_FUNCTION(pcntl_spawn); | |
+PHP_FUNCTION(pcntl_executable); | |
struct php_pcntl_pending_signal { | |
struct php_pcntl_pending_signal *next; | |
Index: php_signal.c | |
=================================================================== | |
--- php_signal.c (revision 290360) | |
+++ php_signal.c (working copy) | |
@@ -20,6 +20,48 @@ | |
#include "php_signal.h" | |
+#ifdef _MSC_VER | |
+ | |
+#if defined(PHP_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1400) | |
+static _invalid_parameter_handler old_invalid_parameter_handler; | |
+void swallow_invalid_parameter_handler(const wchar_t* expression, | |
+ const wchar_t* function, | |
+ const wchar_t* file, | |
+ unsigned int line, | |
+ uintptr_t pReserved) | |
+{ | |
+ /* Do nothing */ | |
+} | |
+#endif | |
+ | |
+/* windows does not HAVE sigaction available to it, instead signal() must | |
+ be used */ | |
+Sigfunc *php_signal(int signo, Sigfunc *func, int restart) | |
+{ | |
+ Sigfunc *value; | |
+ | |
+#if defined(PHP_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1400) | |
+ /* bad voodoo - PHP has a CRT invalid parameter handler | |
+ that's nice, but we'll be checking for errors in a moment | |
+ and don't need double warnings! */ | |
+ old_invalid_parameter_handler = _set_invalid_parameter_handler(swallow_invalid_parameter_handler); | |
+#endif | |
+ | |
+ /* Do the call */ | |
+ value = signal(signo, func); | |
+ | |
+#if defined(PHP_WIN32) && defined(_MSC_VER) && (_MSC_VER >= 1400) | |
+ /* restore the previous handler - my word this is ugly */ | |
+ if (old_invalid_parameter_handler != NULL) { | |
+ _set_invalid_parameter_handler(old_invalid_parameter_handler); | |
+ } | |
+#endif | |
+ | |
+ return value; | |
+} | |
+ | |
+#else | |
+ | |
/* 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, int restart) | |
@@ -42,6 +84,7 @@ | |
return oact.sa_handler; | |
} | |
+#endif | |
/* | |
* Local variables: | |
Index: php_signal.h | |
=================================================================== | |
--- php_signal.h (revision 290360) | |
+++ php_signal.h (working copy) | |
@@ -18,6 +18,7 @@ | |
/* $Id$ */ | |
+#include <php.h> | |
#include <signal.h> | |
#ifndef PHP_SIGNAL_H | |
#define PHP_SIGNAL_H | |
Index: tests/pcntl_exec.phpt | |
=================================================================== | |
--- tests/pcntl_exec.phpt (revision 290360) | |
+++ tests/pcntl_exec.phpt (working copy) | |
@@ -1,12 +1,14 @@ | |
--TEST-- | |
pcntl_exec() | |
--SKIPIF-- | |
-<?php if (!getenv("TEST_PHP_EXECUTABLE") || !is_executable(getenv("TEST_PHP_EXECUTABLE"))) die("skip TEST_PHP_EXECUTABLE not set"); ?> | |
+<?php | |
+ if (!extension_loaded('pcntl')) echo 'skip'; | |
+?> | |
--FILE-- | |
<?php | |
echo "ok\n"; | |
-pcntl_exec(getenv("TEST_PHP_EXECUTABLE")); | |
+pcntl_exec(pcntl_executable()); | |
echo "nok\n"; | |
?> | |
--EXPECT-- | |
-ok | |
+ok | |
\ No newline at end of file | |
Index: tests/pcntl_exec_2.phpt | |
=================================================================== | |
--- tests/pcntl_exec_2.phpt (revision 290360) | |
+++ tests/pcntl_exec_2.phpt (working copy) | |
@@ -1,7 +1,9 @@ | |
--TEST-- | |
-pcntl_exec() 2 | |
+pcntl_exec() with environment variables | |
--SKIPIF-- | |
-<?php if (!getenv("TEST_PHP_EXECUTABLE") || !is_executable(getenv("TEST_PHP_EXECUTABLE"))) die("skip TEST_PHP_EXECUTABLE not set"); ?> | |
+<?php | |
+ if (!extension_loaded('pcntl')) echo 'skip'; | |
+?> | |
--FILE-- | |
<?php | |
if (getenv("PCNTL_EXEC_TEST_IS_CHILD")) { | |
@@ -9,14 +11,13 @@ | |
exit; | |
} | |
echo "ok\n"; | |
-pcntl_exec(getenv("TEST_PHP_EXECUTABLE"), array(__FILE__), array( | |
+pcntl_exec(pcntl_executable(), array(__FILE__), array( | |
b"PCNTL_EXEC_TEST_IS_CHILD" => b"1", | |
- b"FOO" => b"BAR", | |
- 1 => b"long") | |
+ b"FOO" => b"BAR") | |
); | |
echo "nok\n"; | |
?> | |
--EXPECT-- | |
ok | |
-string(3) "BAR" | |
+string(3) "BAR" | |
\ No newline at end of file | |
Index: tests/pcntl_exec_3.phpt | |
=================================================================== | |
--- tests/pcntl_exec_3.phpt (revision 290360) | |
+++ tests/pcntl_exec_3.phpt (working copy) | |
@@ -1,5 +1,9 @@ | |
--TEST-- | |
-pcntl_exec() 3 | |
+pcntl_exec() with bad parameters | |
+--SKIPIF-- | |
+<?php | |
+ if (!extension_loaded('pcntl')) echo 'skip'; | |
+?> | |
--FILE-- | |
<?php | |
var_dump(pcntl_exec()); | |
@@ -12,4 +16,4 @@ | |
NULL | |
Warning: pcntl_exec(): Error has occured: (errno %d) %s | |
-bool(false) | |
+bool(false) | |
\ No newline at end of file | |
Index: tests/pcntl_fork_basic.phpt | |
=================================================================== | |
--- tests/pcntl_fork_basic.phpt (revision 290360) | |
+++ tests/pcntl_fork_basic.phpt (working copy) | |
@@ -7,7 +7,7 @@ | |
--SKIPIF-- | |
<?php | |
if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); | |
- elseif (!extension_loaded('posix')) die('skip posix extension not available'); | |
+ if (!function_exists('pcntl_fork')) die('skip pcntl_fork not available'); | |
?> | |
--FILE-- | |
<?php | |
Index: tests/pcntl_fork_variation.phpt | |
=================================================================== | |
--- tests/pcntl_fork_variation.phpt (revision 290360) | |
+++ tests/pcntl_fork_variation.phpt (working copy) | |
@@ -7,7 +7,7 @@ | |
--SKIPIF-- | |
<?php | |
if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); | |
- elseif (!extension_loaded('posix')) die('skip posix extension not available'); | |
+ if (!function_exists('pcntl_fork')) die('skip pcntl_fork not available'); | |
?> | |
--FILE-- | |
<?php | |
@@ -29,7 +29,7 @@ | |
echo "son ($pid)\n"; | |
$pid2 = pcntl_fork(); | |
if ($pid2 > 0) | |
- { | |
+ { | |
pcntl_wait($status2); | |
echo "son is father of $pid2\n"; | |
} | |
Index: tests/pcntl_signal.phpt | |
=================================================================== | |
--- tests/pcntl_signal.phpt (revision 290360) | |
+++ tests/pcntl_signal.phpt (working copy) | |
@@ -1,24 +1,22 @@ | |
--TEST-- | |
pcntl_signal() | |
--SKIPIF-- | |
-<?php if (!extension_loaded("posix")) die("skip posix extension not available"); ?> | |
+<?php if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); ?> | |
--FILE-- | |
<?php | |
pcntl_signal(SIGTERM, function($signo){ | |
echo "signal dispatched\n"; | |
}); | |
-posix_kill(posix_getpid(), SIGTERM); | |
+pcntl_raise(SIGTERM); | |
pcntl_signal_dispatch(); | |
- | |
var_dump(pcntl_signal()); | |
-var_dump(pcntl_signal(SIGALRM, SIG_IGN)); | |
+var_dump(pcntl_signal(SIGILL, SIG_IGN)); | |
var_dump(pcntl_signal(-1, -1)); | |
var_dump(pcntl_signal(-1, function(){})); | |
-var_dump(pcntl_signal(SIGALRM, "not callable")); | |
+var_dump(pcntl_signal(SIGILL, 'not callable')); | |
- | |
/* test freeing queue in RSHUTDOWN */ | |
-posix_kill(posix_getpid(), SIGTERM); | |
+pcntl_raise(SIGTERM); | |
echo "ok\n"; | |
?> | |
--EXPECTF-- | |
@@ -29,8 +27,6 @@ | |
bool(true) | |
Warning: pcntl_signal(): Invalid value for handle argument specified in %s | |
- | |
-Warning: pcntl_signal(): Error assigning signal %s | |
bool(false) | |
Warning: pcntl_signal(): Error assigning signal %s | |
Index: tests/pcntl_signal_dispatch.phpt | |
=================================================================== | |
--- tests/pcntl_signal_dispatch.phpt (revision 290360) | |
+++ tests/pcntl_signal_dispatch.phpt (working copy) | |
@@ -2,19 +2,16 @@ | |
pcnt_signal_dispatch() | |
--SKIPIF-- | |
<?php | |
- if (!extension_loaded("pcntl")) print "skip"; | |
- elseif (!function_exists("pcntl_signal")) print "skip pcntl_signal() not available"; | |
- elseif (!function_exists("pcntl_signal_dispatch")) print "skip pcntl_signal_dispatch() not available"; | |
- elseif (!function_exists("posix_kill")) print "skip posix_kill() not available"; | |
- elseif (!function_exists("posix_getpid")) print "skip posix_getpid() not available"; | |
+ if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); | |
+ if (!function_exists('pcntl_signal')) die('skip pcntl_signal not available'); | |
+ if (!function_exists('pcntl_signal_dispatch')) die('skip pcntl_signal_dispatch not available'); | |
?> | |
--FILE-- | |
<?php | |
- | |
pcntl_signal(SIGTERM, function ($signo) { echo "Signal handler called!\n"; }); | |
echo "Start!\n"; | |
-posix_kill(posix_getpid(), SIGTERM); | |
+pcntl_raise(SIGTERM); | |
$i = 0; // dummy | |
pcntl_signal_dispatch(); | |
echo "Done!\n"; | |
Index: tests/pcntl_spawn_basic.phpt | |
=================================================================== | |
--- tests/pcntl_spawn_basic.phpt (revision 0) | |
+++ tests/pcntl_spawn_basic.phpt (revision 0) | |
@@ -0,0 +1,21 @@ | |
+--TEST-- | |
+Test function pcntl_spawn() by calling it with its expected arguments | |
+--SKIPIF-- | |
+<?php | |
+ if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); | |
+?> | |
+--FILE-- | |
+<?php | |
+if (getenv("PCNTL_SPAWN_TEST_IS_CHILD")) { | |
+ var_dump(getmypid()); | |
+ var_dump((binary)getenv("FOO")); | |
+ exit; | |
+} | |
+$pid = pcntl_spawn(pcntl_executable(), NULL, array(__FILE__), array( | |
+ b"PCNTL_SPAWN_TEST_IS_CHILD" => b"1", | |
+ b"FOO" => b"BAR")); | |
+ | |
+pcntl_waitpid($pid, $status, null); | |
+var_dump($pid); | |
+?> | |
+--EXPECTF-- | |
Index: tests/pcntl_waitpid.phpt | |
=================================================================== | |
--- tests/pcntl_waitpid.phpt (revision 0) | |
+++ tests/pcntl_waitpid.phpt (revision 0) | |
@@ -0,0 +1,41 @@ | |
+--TEST-- | |
+pcntl_waitpid functionality | |
+--SKIPIF-- | |
+<?php | |
+ if (!extension_loaded('pcntl')) echo 'skip'; | |
+?> | |
+--FILE-- | |
+<?php | |
+$pid = pcntl_spawn(); | |
+ | |
+function test_exit_waits(){ | |
+ print "\n\nTesting pcntl_wifexited and wexitstatus...."; | |
+ | |
+ $pid=pcntl_fork(); | |
+ if ($pid==0) { | |
+ sleep(1); | |
+ exit(-1); | |
+ } else { | |
+ $options=0; | |
+ pcntl_waitpid($pid, $status, $options); | |
+ if ( pcntl_wifexited($status) ) print "\nExited With: ". pcntl_wexitstatus($status); | |
+ } | |
+} | |
+ | |
+ | |
+print "Staring wait.h tests...."; | |
+test_exit_waits(); | |
+test_exit_signal(); | |
+test_stop_signal(); | |
+?> | |
+--EXPECT-- | |
+Staring wait.h tests.... | |
+ | |
+Testing pcntl_wifexited and wexitstatus.... | |
+Exited With: 255 | |
+ | |
+Testing pcntl_wifsignaled.... | |
+Process was terminated by signal : SIGTERM | |
+ | |
+Testing pcntl_wifstopped and pcntl_wstopsig.... | |
+Process was stoped by signal : SIGSTOP | |
Index: tests/pcntl_wifexited.phpt | |
=================================================================== | |
--- tests/pcntl_wifexited.phpt (revision 0) | |
+++ tests/pcntl_wifexited.phpt (revision 0) | |
@@ -0,0 +1,34 @@ | |
+--TEST-- | |
+pcntl_wifexited() | |
+--SKIPIF-- | |
+<?php if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); ?> | |
+--FILE-- | |
+<?php | |
+if (getenv('is_child')) { | |
+ exit; | |
+} | |
+if (getenv('is_child_bad')) { | |
+ exit(42); | |
+} | |
+$pid = pcntl_spawn(pcntl_executable(), NULL, array(__FILE__), array( | |
+ 'is_child' => '1')); | |
+ | |
+pcntl_waitpid($pid, $status); | |
+ | |
+var_dump(pcntl_wifexited($status)); | |
+ | |
+$pid = pcntl_spawn(pcntl_executable(), NULL, array(__FILE__), array( | |
+ 'is_child_bad' => '1')); | |
+ | |
+pcntl_waitpid($pid, $status); | |
+ | |
+var_dump(pcntl_wifexited($status)); | |
+ | |
+var_dump(pcntl_wifexited()); | |
+?> | |
+--EXPECTF-- | |
+bool(true) | |
+bool(false) | |
+ | |
+Warning: pcntl_wifexited() expects exactly 1 parameter, 0 given in %s on line %d | |
+NULL | |
\ No newline at end of file | |
Index: tests/signal_closure_handler.phpt | |
=================================================================== | |
--- tests/signal_closure_handler.phpt (revision 290360) | |
+++ tests/signal_closure_handler.phpt (working copy) | |
@@ -1,11 +1,9 @@ | |
--TEST-- | |
-Closures as a signal handler | |
+Using ticks for signal handling | |
--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"; | |
+ if (!extension_loaded('pcntl')) die('skip pcntl extension not available'); | |
+ if (!function_exists('pcntl_signal')) die('skip pcntl_signal not available'); | |
?> | |
--FILE-- | |
<?php | |
@@ -14,7 +12,7 @@ | |
pcntl_signal(SIGTERM, function ($signo) { echo "Signal handler called!\n"; }); | |
echo "Start!\n"; | |
-posix_kill(posix_getpid(), SIGTERM); | |
+pcntl_raise(SIGTERM); | |
$i = 0; // dummy | |
echo "Done!\n"; | |
Index: TODO | |
=================================================================== | |
--- TODO (revision 0) | |
+++ TODO (revision 0) | |
@@ -0,0 +1,7 @@ | |
+1. put hashtable for storing child process PIDs in for win32 into globals | |
+2. make spawn store the child process PIDs for nowait | |
+3. make waitpid remove the child process PID if it's closed | |
+4. make wait "waitformultipleobjects" on the child process hash table and remove them if they're done | |
+ | |
+5. create win_pcntl.h and win_pcntl.c with windows specific stuff | |
+6. deal with signals - ick! | |
\ No newline at end of file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment