summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntony Dovgal <tony2001@php.net>2014-12-11 17:01:55 +0300
committerJulien Pauli <jpauli@php.net>2015-05-13 15:34:17 +0200
commit7e0e88820a2cf6ef3804383413fe1b7f7538962a (patch)
tree466c409fc80efb00d6ff339b4e6ff51d1b454602
parent917f292dc4ab65ac0815d7240ea054e4efca347d (diff)
downloadphp-git-7e0e88820a2cf6ef3804383413fe1b7f7538962a.tar.gz
add rusage support to wait() and waitpid()
patch by Anton Stepanenko
-rw-r--r--ext/pcntl/config.m42
-rw-r--r--ext/pcntl/pcntl.c106
-rw-r--r--ext/pcntl/tests/pcntl_wait_rusage1.phpt50
-rw-r--r--ext/pcntl/tests/pcntl_waitpid_rusage1.phpt50
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