diff options
author | Antony Dovgal <tony2001@php.net> | 2014-12-11 17:01:55 +0300 |
---|---|---|
committer | Julien Pauli <jpauli@php.net> | 2015-05-13 15:34:17 +0200 |
commit | 7e0e88820a2cf6ef3804383413fe1b7f7538962a (patch) | |
tree | 466c409fc80efb00d6ff339b4e6ff51d1b454602 /ext/pcntl | |
parent | 917f292dc4ab65ac0815d7240ea054e4efca347d (diff) | |
download | php-git-7e0e88820a2cf6ef3804383413fe1b7f7538962a.tar.gz |
add rusage support to wait() and waitpid()
patch by Anton Stepanenko
Diffstat (limited to 'ext/pcntl')
-rw-r--r-- | ext/pcntl/config.m4 | 2 | ||||
-rw-r--r-- | ext/pcntl/pcntl.c | 106 | ||||
-rw-r--r-- | ext/pcntl/tests/pcntl_wait_rusage1.phpt | 50 | ||||
-rw-r--r-- | ext/pcntl/tests/pcntl_waitpid_rusage1.phpt | 50 |
4 files changed, 197 insertions, 11 deletions
diff --git a/ext/pcntl/config.m4 b/ext/pcntl/config.m4 index 2ef07f140c..70e0aeb008 100644 --- a/ext/pcntl/config.m4 +++ b/ext/pcntl/config.m4 @@ -9,6 +9,6 @@ if test "$PHP_PCNTL" != "no"; then AC_CHECK_FUNCS(fork, [ AC_DEFINE(HAVE_FORK,1,[ ]) ], [ AC_MSG_ERROR(pcntl: fork() not supported by this platform) ]) AC_CHECK_FUNCS(waitpid, [ AC_DEFINE(HAVE_WAITPID,1,[ ]) ], [ AC_MSG_ERROR(pcntl: waitpid() not supported by this platform) ]) AC_CHECK_FUNCS(sigaction, [ AC_DEFINE(HAVE_SIGACTION,1,[ ]) ], [ AC_MSG_ERROR(pcntl: sigaction() not supported by this platform) ]) - AC_CHECK_FUNCS([getpriority setpriority wait3 sigprocmask sigwaitinfo sigtimedwait]) + AC_CHECK_FUNCS([getpriority setpriority wait3 wait4 sigprocmask sigwaitinfo sigtimedwait]) PHP_NEW_EXTENSION(pcntl, pcntl.c php_signal.c, $ext_shared, cli) fi diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index 7e75139771..f152ad8814 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -57,11 +57,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_waitpid, 0, 0, 2) ZEND_ARG_INFO(0, pid) ZEND_ARG_INFO(1, status) ZEND_ARG_INFO(0, options) + ZEND_ARG_INFO(1, rusage) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_wait, 0, 0, 1) ZEND_ARG_INFO(1, status) ZEND_ARG_INFO(0, options) + ZEND_ARG_INFO(1, rusage) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_pcntl_signal, 0, 0, 2) @@ -577,54 +579,128 @@ PHP_FUNCTION(pcntl_alarm) } /* }}} */ -/* {{{ proto int pcntl_waitpid(int pid, int &status, int options) +#define PHP_RUSAGE_PARA(from, to, field) \ + add_assoc_long(to, #field, from.field) +#if !defined(_OSD_POSIX) && !defined(__BEOS__) /* BS2000 has only a few fields in the rusage struct */ + #define PHP_RUSAGE_SPECIAL(from, to) \ + PHP_RUSAGE_PARA(from, to, ru_oublock); \ + PHP_RUSAGE_PARA(from, to, ru_inblock); \ + PHP_RUSAGE_PARA(from, to, ru_msgsnd); \ + PHP_RUSAGE_PARA(from, to, ru_msgrcv); \ + PHP_RUSAGE_PARA(from, to, ru_maxrss); \ + PHP_RUSAGE_PARA(from, to, ru_ixrss); \ + PHP_RUSAGE_PARA(from, to, ru_idrss); \ + PHP_RUSAGE_PARA(from, to, ru_minflt); \ + PHP_RUSAGE_PARA(from, to, ru_majflt); \ + PHP_RUSAGE_PARA(from, to, ru_nsignals); \ + PHP_RUSAGE_PARA(from, to, ru_nvcsw); \ + PHP_RUSAGE_PARA(from, to, ru_nivcsw); \ + PHP_RUSAGE_PARA(from, to, ru_nswap); +#else /*_OSD_POSIX*/ + #define PHP_RUSAGE_SPECIAL(from, to) +#endif + +#define PHP_RUSAGE_COMMON(from ,to) \ + PHP_RUSAGE_PARA(from, to, ru_utime.tv_usec); \ + PHP_RUSAGE_PARA(from, to, ru_utime.tv_sec); \ + PHP_RUSAGE_PARA(from, to, ru_stime.tv_usec); \ + PHP_RUSAGE_PARA(from, to, ru_stime.tv_sec); + +#define PHP_RUSAGE_TO_ARRAY(from, to) \ + if (to) { \ + PHP_RUSAGE_SPECIAL(from, to) \ + PHP_RUSAGE_COMMON(from, to); \ + } + +/* {{{ proto int pcntl_waitpid(int pid, int &status, int options, array &$rusage) Waits on or returns the status of a forked child as defined by the waitpid() system call */ PHP_FUNCTION(pcntl_waitpid) { zend_long pid, options = 0; - zval *z_status = NULL; + zval *z_status = NULL, *z_rusage = NULL; int status; pid_t child_id; +#ifdef HAVE_WAIT4 + struct rusage rusage; +#endif - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/|l", &pid, &z_status, &options) == FAILURE) + if (zend_parse_parameters(ZEND_NUM_ARGS(), "lz/|lz/", &pid, &z_status, &options, &z_rusage) == FAILURE) return; convert_to_long_ex(z_status); status = Z_LVAL_P(z_status); +#ifdef HAVE_WAIT4 + if (z_rusage) { + if (Z_TYPE_P(z_rusage) != IS_ARRAY) { + zval_dtor(z_rusage); + array_init(z_rusage); + } else { + zend_hash_clean(Z_ARRVAL_P(z_rusage)); + } + } + + if (z_rusage) { + memset(&rusage, 0, sizeof(struct rusage)); + child_id = wait4((pid_t) pid, &status, options, &rusage); + } else { + child_id = waitpid((pid_t) pid, &status, options); + } +#else child_id = waitpid((pid_t) pid, &status, options); +#endif if (child_id < 0) { PCNTL_G(last_error) = errno; } +#ifdef HAVE_WAIT4 + if (child_id > 0) { + PHP_RUSAGE_TO_ARRAY(rusage, z_rusage); + } +#endif + Z_LVAL_P(z_status) = status; RETURN_LONG((zend_long) child_id); } /* }}} */ -/* {{{ proto int pcntl_wait(int &status) +/* {{{ proto int pcntl_wait(int &status, int $options, array &$rusage) Waits on or returns the status of a forked child as defined by the waitpid() system call */ PHP_FUNCTION(pcntl_wait) { zend_long options = 0; - zval *z_status = NULL; + zval *z_status = NULL, *z_rusage = NULL; int status; pid_t child_id; +#ifdef HAVE_WAIT3 + struct rusage rusage; +#endif - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/|l", &z_status, &options) == FAILURE) + if (zend_parse_parameters(ZEND_NUM_ARGS(), "z/|lz/", &z_status, &options, &z_rusage) == FAILURE) return; convert_to_long_ex(z_status); status = Z_LVAL_P(z_status); #ifdef HAVE_WAIT3 - if(options) { - child_id = wait3(&status, options, NULL); + if (z_rusage) { + if (Z_TYPE_P(z_rusage) != IS_ARRAY) { + zval_dtor(z_rusage); + array_init(z_rusage); + } else { + zend_hash_clean(Z_ARRVAL_P(z_rusage)); + } } - else { + + if (z_rusage) { + memset(&rusage, 0, sizeof(struct rusage)); + child_id = wait3(&status, options, &rusage); + } else if (options) { + child_id = wait3(&status, options, NULL); + } else { child_id = wait(&status); } #else @@ -634,13 +710,23 @@ PHP_FUNCTION(pcntl_wait) PCNTL_G(last_error) = errno; } +#ifdef HAVE_WAIT3 + if (child_id > 0) { + PHP_RUSAGE_TO_ARRAY(rusage, z_rusage); + } +#endif Z_LVAL_P(z_status) = status; RETURN_LONG((zend_long) child_id); } /* }}} */ -/* {{{ proto bool pcntl_wifexited(int status) +#undef PHP_RUSAGE_PARA +#undef PHP_RUSAGE_SPECIAL +#undef PHP_RUSAGE_COMMON +#undef PHP_RUSAGE_TO_ARRAY + +/* {{{ proto bool pcntl_wifexited(int status) Returns true if the child status code represents a successful exit */ PHP_FUNCTION(pcntl_wifexited) { diff --git a/ext/pcntl/tests/pcntl_wait_rusage1.phpt b/ext/pcntl/tests/pcntl_wait_rusage1.phpt new file mode 100644 index 0000000000..9e95f0020b --- /dev/null +++ b/ext/pcntl/tests/pcntl_wait_rusage1.phpt @@ -0,0 +1,50 @@ +--TEST-- +pcntl_wait() and rusage +--SKIPIF-- +<?php if (!extension_loaded("pcntl")) print "skip"; ?> +<?php if (!extension_loaded("posix")) die("skip posix extension not available"); ?> +--FILE-- +<?php +$pid = pcntl_fork(); +if ($pid == 1) { + die("failed"); +} else if ($pid) { + $status = 0; + var_dump(pcntl_wait($status, WUNTRACED, $rusage)); + var_dump($rusage['ru_utime.tv_sec']); + var_dump($rusage['ru_utime.tv_usec']); + + posix_kill($pid, SIGCONT); + + $rusage = array(1,2,3); + pcntl_wait($status, WUNTRACED, $rusage); + var_dump($rusage['ru_utime.tv_sec']); + var_dump($rusage['ru_utime.tv_usec']); + + $rusage = "string"; + pcntl_wait($status, 0, $rusage); + var_dump(gettype($rusage)); + var_dump(count($rusage)); + + $rusage = new stdClass; + pcntl_wait($status, 0, $rusage); + var_dump(gettype($rusage)); + var_dump(count($rusage)); + + echo "END\n"; +} else { + posix_kill(posix_getpid(), SIGSTOP); + exit(42); +} +?> +--EXPECTF-- +int(%d) +int(%d) +int(%d) +int(%d) +int(%d) +string(5) "array" +int(0) +string(5) "array" +int(0) +END diff --git a/ext/pcntl/tests/pcntl_waitpid_rusage1.phpt b/ext/pcntl/tests/pcntl_waitpid_rusage1.phpt new file mode 100644 index 0000000000..b5c9aae312 --- /dev/null +++ b/ext/pcntl/tests/pcntl_waitpid_rusage1.phpt @@ -0,0 +1,50 @@ +--TEST-- +pcntl_waitpid() and rusage +--SKIPIF-- +<?php if (!extension_loaded("pcntl")) print "skip"; ?> +<?php if (!extension_loaded("posix")) die("skip posix extension not available"); ?> +--FILE-- +<?php +$pid = pcntl_fork(); +if ($pid == 1) { + die("failed"); +} else if ($pid) { + $status = 0; + var_dump(pcntl_waitpid($pid, $status, WUNTRACED, $rusage)); + var_dump($rusage['ru_utime.tv_sec']); + var_dump($rusage['ru_utime.tv_usec']); + + posix_kill($pid, SIGCONT); + + $rusage = array(1,2,3); + pcntl_waitpid($pid, $status, WUNTRACED, $rusage); + var_dump($rusage['ru_utime.tv_sec']); + var_dump($rusage['ru_utime.tv_usec']); + + $rusage = "string"; + pcntl_waitpid($pid, $status, 0, $rusage); + var_dump(gettype($rusage)); + var_dump(count($rusage)); + + $rusage = new stdClass; + pcntl_waitpid($pid, $status, 0, $rusage); + var_dump(gettype($rusage)); + var_dump(count($rusage)); + + echo "END\n"; +} else { + posix_kill(posix_getpid(), SIGSTOP); + exit(42); +} +?> +--EXPECTF-- +int(%d) +int(%d) +int(%d) +int(%d) +int(%d) +string(5) "array" +int(0) +string(5) "array" +int(0) +END |