-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Extend pcntl_waitid with rusage parameter #15921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure if I like using undocumented syscalls ... There are already some syscalls used here so I'm not objecting but not sure if there is much value in it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bukka Thanks for the review! I agree that having to use the raw I think it's nice to round off the PHP pcntl_wait* function family functionality with a rich and consistent API, such as FreeBSD and NetBSD have with GNU libc has had |
||
# 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; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1006,8 +1006,11 @@ function pcntl_fork(): int {} | |
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure if we have to bother with these thus asking the stub wizard assistance :) once confirmed I ll merge shortly. Thanks for your work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kocsismate Could you please take a quick look at the stub? |
||
* @param array $resource_usage | ||
*/ | ||
function pcntl_waitid(int $idtype = P_ALL, ?int $id = null, &$info = [], int $flags = WEXITED, &$resource_usage = []): bool {} | ||
#endif | ||
|
||
/** | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@devnexen This is sort of an off topic but why SYS_pidfd_open is not checked in this way too. There is a check for pidfd_open function but how is that actually passing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes indeed, I'll change that very soon. pidfd_open being a glibc wrapper exclusive (for now at least), it all worked for me locally.