mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
ext/pcntl: Added rusage parameter to pcntl_waitid
This functionality is not part of the POSIX interface. - On FreeBSD, the wait6 system call provides it - On Linux, the raw waitid system call provides it (glibc does not) close GH-15921
This commit is contained in:
committed by
David Carlier
parent
ca49a7bec2
commit
aea3ade74f
3
NEWS
3
NEWS
@@ -134,6 +134,9 @@ PHP NEWS
|
||||
- Output:
|
||||
. Fixed calculation of aligned buffer size. (cmb)
|
||||
|
||||
- PCNTL:
|
||||
. Extend pcntl_waitid with rusage parameter. (vrza)
|
||||
|
||||
- PCRE:
|
||||
. Upgraded to pre2lib from 10.44 to 10.45. (nielsdos)
|
||||
. Remove PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK from pcre compile options.
|
||||
|
||||
@@ -289,6 +289,8 @@ PHP 8.5 UPGRADE NOTES
|
||||
|
||||
- PCNTL:
|
||||
. pcntl_exec() now has a formal return type of false.
|
||||
. pcntl_waitid() takes an additional resource_usage argument to
|
||||
gather various platform specific metrics about the child process.
|
||||
|
||||
- PDO_PGSQL:
|
||||
. PDO::pgsqlCopyFromArray also supports inputs as Iterable.
|
||||
|
||||
@@ -25,6 +25,8 @@ if test "$PHP_PCNTL" != "no"; then
|
||||
wait3
|
||||
wait4
|
||||
waitid
|
||||
wait6
|
||||
syscall
|
||||
]))
|
||||
|
||||
AC_CHECK_FUNCS([WIFCONTINUED],,
|
||||
@@ -43,6 +45,9 @@ if test "$PHP_PCNTL" != "no"; then
|
||||
]),,,
|
||||
[#include <sys/wait.h>])
|
||||
|
||||
AC_CHECK_DECLS([SYS_waitid],,,
|
||||
[#include <sys/syscall.h>])
|
||||
|
||||
dnl if unsupported, -1 means automatically ENOSYS in this context
|
||||
AC_CACHE_CHECK([if sched_getcpu is supported], [php_cv_func_sched_getcpu],
|
||||
[AC_RUN_IFELSE([AC_LANG_SOURCE([
|
||||
|
||||
@@ -125,7 +125,15 @@ typedef psetid_t cpu_set_t;
|
||||
#include <pthread/qos.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PIDFD_OPEN
|
||||
#if defined(__linux__) && defined(HAVE_DECL_SYS_WAITID) && HAVE_DECL_SYS_WAITID == 1 && defined(HAVE_SYSCALL)
|
||||
#define HAVE_LINUX_RAW_SYSCALL_WAITID 1
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LINUX_RAW_SYSCALL_WAITID)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_PIDFD_OPEN) || defined(HAVE_LINUX_RAW_SYSCALL_WAITID)
|
||||
#include <sys/syscall.h>
|
||||
#endif
|
||||
|
||||
@@ -401,19 +409,49 @@ PHP_FUNCTION(pcntl_waitid)
|
||||
bool id_is_null = 1;
|
||||
zval *user_siginfo = NULL;
|
||||
zend_long options = WEXITED;
|
||||
zval *z_rusage = NULL;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(0, 4)
|
||||
siginfo_t siginfo;
|
||||
int status;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_START(0, 5)
|
||||
Z_PARAM_OPTIONAL
|
||||
Z_PARAM_LONG(idtype)
|
||||
Z_PARAM_LONG_OR_NULL(id, id_is_null)
|
||||
Z_PARAM_ZVAL(user_siginfo)
|
||||
Z_PARAM_LONG(options)
|
||||
Z_PARAM_ZVAL(z_rusage)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
errno = 0;
|
||||
siginfo_t siginfo;
|
||||
memset(&siginfo, 0, sizeof(siginfo_t));
|
||||
|
||||
int status = waitid((idtype_t) idtype, (id_t) id, &siginfo, (int) options);
|
||||
#if defined(HAVE_WAIT6) || defined(HAVE_LINUX_RAW_SYSCALL_WAITID)
|
||||
if (z_rusage) {
|
||||
z_rusage = zend_try_array_init(z_rusage);
|
||||
if (!z_rusage) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
struct rusage rusage;
|
||||
# if defined(HAVE_WAIT6) /* FreeBSD */
|
||||
struct __wrusage wrusage;
|
||||
memset(&wrusage, 0, sizeof(struct __wrusage));
|
||||
pid_t pid = wait6((idtype_t) idtype, (id_t) id, &status, (int) options, &wrusage, &siginfo);
|
||||
status = pid > 0 ? 0 : pid;
|
||||
memcpy(&rusage, &wrusage.wru_self, sizeof(struct rusage));
|
||||
# else /* Linux */
|
||||
memset(&rusage, 0, sizeof(struct rusage));
|
||||
status = syscall(SYS_waitid, (idtype_t) idtype, (id_t) id, &siginfo, (int) options, &rusage);
|
||||
# endif
|
||||
if (status == 0) {
|
||||
PHP_RUSAGE_TO_ARRAY(rusage, z_rusage);
|
||||
}
|
||||
} else { /* POSIX */
|
||||
status = waitid((idtype_t) idtype, (id_t) id, &siginfo, (int) options);
|
||||
}
|
||||
#else /* POSIX */
|
||||
status = waitid((idtype_t) idtype, (id_t) id, &siginfo, (int) options);
|
||||
#endif
|
||||
|
||||
if (status == -1) {
|
||||
PCNTL_G(last_error) = errno;
|
||||
|
||||
@@ -1006,8 +1006,11 @@ const PCNTL_ECAPMODE = UNKNOWN;
|
||||
function pcntl_waitpid(int $process_id, &$status, int $flags = 0, &$resource_usage = []): int {}
|
||||
|
||||
#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1
|
||||
/** @param array $info */
|
||||
function pcntl_waitid(int $idtype = P_ALL, ?int $id = null, &$info = [], int $flags = WEXITED): bool {}
|
||||
/**
|
||||
* @param array $info
|
||||
* @param array $resource_usage
|
||||
*/
|
||||
function pcntl_waitid(int $idtype = P_ALL, ?int $id = null, &$info = [], int $flags = WEXITED, &$resource_usage = []): bool {}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
3
ext/pcntl/pcntl_arginfo.h
generated
3
ext/pcntl/pcntl_arginfo.h
generated
@@ -1,5 +1,5 @@
|
||||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: c637fe2de641cfd8f0ff83a908ac59bf63a68e44 */
|
||||
* Stub hash: 5e4b066d70fa264c7de3ba4b2113369c34c33e43 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
@@ -17,6 +17,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_waitid, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, id, IS_LONG, 1, "null")
|
||||
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, info, "[]")
|
||||
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "WEXITED")
|
||||
ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, resource_usage, "[]")
|
||||
ZEND_END_ARG_INFO()
|
||||
#endif
|
||||
|
||||
|
||||
@@ -26,10 +26,12 @@ if ($pid == -1) {
|
||||
} else {
|
||||
pcntl_signal(SIGUSR1, function ($_signo, $_siginfo) { exit(42); });
|
||||
posix_kill(posix_getpid(), SIGSTOP);
|
||||
pcntl_signal_dispatch();
|
||||
sleep(42);
|
||||
pcntl_signal_dispatch();
|
||||
exit(6);
|
||||
$nanoseconds = 100;
|
||||
while (true) {
|
||||
pcntl_signal_dispatch();
|
||||
time_nanosleep(0, $nanoseconds);
|
||||
$nanoseconds *= 2;
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
|
||||
72
ext/pcntl/tests/pcntl_waitid_rusage.phpt
Normal file
72
ext/pcntl/tests/pcntl_waitid_rusage.phpt
Normal file
@@ -0,0 +1,72 @@
|
||||
--TEST--
|
||||
pcntl_waitid() and rusage
|
||||
--EXTENSIONS--
|
||||
pcntl
|
||||
posix
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!function_exists('pcntl_waitid')) die('skip pcntl_waitid unavailable');
|
||||
if (!str_contains(PHP_OS, 'Linux') && !str_contains(PHP_OS, 'FreeBSD')) {
|
||||
die('skip pcntl_waitid can return rusage only on FreeBSD and Linux');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
$pid = pcntl_fork();
|
||||
if ($pid == -1) {
|
||||
die('failed');
|
||||
} else if ($pid) {
|
||||
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WSTOPPED, $rusage));
|
||||
var_dump($rusage['ru_utime.tv_sec']);
|
||||
var_dump($rusage['ru_utime.tv_usec']);
|
||||
|
||||
$rusage = array(1,2,3);
|
||||
posix_kill($pid, SIGCONT);
|
||||
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WCONTINUED, $rusage));
|
||||
var_dump($rusage['ru_utime.tv_sec']);
|
||||
var_dump($rusage['ru_utime.tv_usec']);
|
||||
|
||||
posix_kill($pid, SIGUSR1);
|
||||
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WEXITED, $rusage));
|
||||
var_dump($rusage['ru_maxrss']);
|
||||
var_dump($siginfo['status']);
|
||||
|
||||
$rusage = 'string';
|
||||
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WEXITED | WNOHANG, $rusage));
|
||||
var_dump(gettype($rusage));
|
||||
var_dump(count($rusage));
|
||||
|
||||
$rusage = new stdClass;
|
||||
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WEXITED | WNOHANG, $rusage));
|
||||
var_dump(gettype($rusage));
|
||||
var_dump(count($rusage));
|
||||
|
||||
fwrite(STDOUT, 'END' . PHP_EOL);
|
||||
} else {
|
||||
pcntl_signal(SIGUSR1, function ($_signo, $_siginfo) { exit(42); });
|
||||
posix_kill(posix_getpid(), SIGSTOP);
|
||||
$nanoseconds = 100;
|
||||
while (true) {
|
||||
pcntl_signal_dispatch();
|
||||
time_nanosleep(0, $nanoseconds);
|
||||
$nanoseconds *= 2;
|
||||
}
|
||||
}
|
||||
?>
|
||||
--EXPECTF--
|
||||
bool(true)
|
||||
int(%d)
|
||||
int(%d)
|
||||
bool(true)
|
||||
int(%d)
|
||||
int(%d)
|
||||
bool(true)
|
||||
int(%d)
|
||||
int(42)
|
||||
bool(false)
|
||||
string(5) "array"
|
||||
int(0)
|
||||
bool(false)
|
||||
string(5) "array"
|
||||
int(0)
|
||||
END
|
||||
Reference in New Issue
Block a user