From 4e8634328869cbc9ec4355f05c1d831baa174dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladimir=20Vrzi=C4=87?= Date: Mon, 16 Sep 2024 17:59:40 +0200 Subject: [PATCH] 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) Changed int to pid_t --- ext/pcntl/config.m4 | 5 ++ ext/pcntl/pcntl.c | 46 +++++++++++++-- ext/pcntl/pcntl.stub.php | 7 ++- ext/pcntl/pcntl_arginfo.h | 3 +- ext/pcntl/tests/pcntl_waitid.phpt | 10 ++-- ext/pcntl/tests/pcntl_waitid_rusage.phpt | 72 ++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 ext/pcntl/tests/pcntl_waitid_rusage.phpt diff --git a/ext/pcntl/config.m4 b/ext/pcntl/config.m4 index ce26a6efd2ead..3efa8a53cad1e 100644 --- a/ext/pcntl/config.m4 +++ b/ext/pcntl/config.m4 @@ -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 ]) + AC_CHECK_DECLS([SYS_waitid],,, + [#include ]) + 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([ diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index e6cba81d98856..9b6fd7f803fdb 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -125,7 +125,15 @@ typedef psetid_t cpu_set_t; #include #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 +#endif + +#if defined(HAVE_PIDFD_OPEN) || defined(HAVE_LINUX_RAW_SYSCALL_WAITID) #include #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; diff --git a/ext/pcntl/pcntl.stub.php b/ext/pcntl/pcntl.stub.php index c62a40139d9ed..3f3800c50abe5 100644 --- a/ext/pcntl/pcntl.stub.php +++ b/ext/pcntl/pcntl.stub.php @@ -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 + * @param array $resource_usage + */ + function pcntl_waitid(int $idtype = P_ALL, ?int $id = null, &$info = [], int $flags = WEXITED, &$resource_usage = []): bool {} #endif /** diff --git a/ext/pcntl/pcntl_arginfo.h b/ext/pcntl/pcntl_arginfo.h index 8da7cb70a6aa7..c6e41f44289db 100644 --- a/ext/pcntl/pcntl_arginfo.h +++ b/ext/pcntl/pcntl_arginfo.h @@ -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 diff --git a/ext/pcntl/tests/pcntl_waitid.phpt b/ext/pcntl/tests/pcntl_waitid.phpt index b00f26f81fa2e..e297cd107a473 100644 --- a/ext/pcntl/tests/pcntl_waitid.phpt +++ b/ext/pcntl/tests/pcntl_waitid.phpt @@ -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-- diff --git a/ext/pcntl/tests/pcntl_waitid_rusage.phpt b/ext/pcntl/tests/pcntl_waitid_rusage.phpt new file mode 100644 index 0000000000000..8df148357d1c8 --- /dev/null +++ b/ext/pcntl/tests/pcntl_waitid_rusage.phpt @@ -0,0 +1,72 @@ +--TEST-- +pcntl_waitid() and rusage +--EXTENSIONS-- +pcntl +posix +--SKIPIF-- + +--FILE-- + +--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