diff --git a/NEWS b/NEWS index 6feb44d4b9b64..5416ffec8d7f7 100644 --- a/NEWS +++ b/NEWS @@ -164,6 +164,7 @@ PHP NEWS . Added pcntl_getqos_class/pcntl_setqos_class for macOs. (David Carlier) . Added SIGCKPT/SIGCKPTEXIT constants for DragonFlyBSD. (David Carlier) . Added FreeBSD's SIGTRAP handling to pcntl_siginfo_to_zval. (David Carlier) + . Added POSIX pcntl_waitid. (Vladimir Vrzić) - PCRE: . Upgrade bundled pcre2lib to version 10.43. (nielsdos) diff --git a/ext/pcntl/config.m4 b/ext/pcntl/config.m4 index 5357e7dbc01f0..c6a25171ec5c4 100644 --- a/ext/pcntl/config.m4 +++ b/ext/pcntl/config.m4 @@ -24,8 +24,16 @@ if test "$PHP_PCNTL" != "no"; then unshare wait3 wait4 + waitid ])) + AC_CHECK_FUNCS([WIFCONTINUED],, + [AC_CHECK_DECL([WIFCONTINUED], [AC_DEFINE([HAVE_WIFCONTINUED], [1])],, + [#include ])]) + + AC_CHECK_DECLS([WCONTINUED, WEXITED, WSTOPPED, WNOWAIT, P_ALL, P_PIDFD, P_UID, P_JAILID],,, + [#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 b26bde1ff8fcc..f687fecf6c24f 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -29,7 +29,6 @@ #include "php.h" #include "ext/standard/info.h" -#include "php_pcntl.h" #include "php_signal.h" #include "php_ticks.h" #include "zend_fibers.h" @@ -40,6 +39,22 @@ #include #endif +#ifdef HAVE_WAITID +#if defined (HAVE_DECL_P_ALL) && HAVE_DECL_P_ALL == 1 +#define HAVE_POSIX_IDTYPES 1 +#endif +#if defined (HAVE_DECL_P_PIDFD) && HAVE_DECL_P_PIDFD == 1 +#define HAVE_LINUX_IDTYPES 1 +#endif +#if defined (HAVE_DECL_P_UID) && HAVE_DECL_P_UID == 1 +#define HAVE_NETBSD_IDTYPES 1 +#endif +#if defined (HAVE_DECL_P_JAILID) && HAVE_DECL_P_JAILID == 1 +#define HAVE_FREEBSD_IDTYPES 1 +#endif +#endif + +#include "php_pcntl.h" #include #if defined(HAVE_UNSHARE) || defined(HAVE_SCHED_SETAFFINITY) || defined(HAVE_SCHED_GETCPU) #include @@ -385,6 +400,39 @@ PHP_FUNCTION(pcntl_waitpid) } /* }}} */ +#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1 +PHP_FUNCTION(pcntl_waitid) +{ + zend_long idtype = P_ALL; + zend_long id = 0; + bool id_is_null = 1; + zval *user_siginfo = NULL; + zend_long options = WEXITED; + + ZEND_PARSE_PARAMETERS_START(0, 4) + 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) + ZEND_PARSE_PARAMETERS_END(); + + errno = 0; + siginfo_t siginfo; + + int status = waitid((idtype_t) idtype, (id_t) id, &siginfo, (int) options); + + if (status == -1) { + PCNTL_G(last_error) = errno; + RETURN_FALSE; + } + + pcntl_siginfo_to_zval(SIGCHLD, &siginfo, user_siginfo); + + RETURN_TRUE; +} +#endif + /* {{{ Waits on or returns the status of a forked child as defined by the waitpid() system call */ PHP_FUNCTION(pcntl_wait) { @@ -1685,7 +1733,7 @@ PHP_FUNCTION(pcntl_setcpuaffinity) zend_argument_value_error(2, "cpu id must be between 0 and " ZEND_ULONG_FMT " (" ZEND_LONG_FMT ")", maxcpus, cpu); RETURN_THROWS(); } - + if (!PCNTL_CPU_ISSET(cpu, mask)) { PCNTL_CPU_SET(cpu, mask); } diff --git a/ext/pcntl/pcntl.stub.php b/ext/pcntl/pcntl.stub.php index 7db1e8ed594e2..7b72c00453966 100644 --- a/ext/pcntl/pcntl.stub.php +++ b/ext/pcntl/pcntl.stub.php @@ -25,6 +25,82 @@ */ const WCONTINUED = UNKNOWN; #endif +#if defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1 +/** + * @var int + * @cvalue LONG_CONST(WEXITED) + */ +const WEXITED = UNKNOWN; +#endif +#if defined (HAVE_DECL_WSTOPPED) && HAVE_DECL_WSTOPPED == 1 +/** + * @var int + * @cvalue LONG_CONST(WSTOPPED) + */ +const WSTOPPED = UNKNOWN; +#endif +#if defined (HAVE_DECL_WNOWAIT) && HAVE_DECL_WNOWAIT== 1 +/** + * @var int + * @cvalue LONG_CONST(WNOWAIT) + */ +const WNOWAIT = UNKNOWN; +#endif + +#ifdef HAVE_WAITID +/* First argument to waitid */ +#ifdef HAVE_POSIX_IDTYPES +/** + * @var int + * @cvalue LONG_CONST(P_ALL) + */ +const P_ALL = UNKNOWN; +/** + * @var int + * @cvalue LONG_CONST(P_PID) + */ +const P_PID = UNKNOWN; +/** + * @var int + * @cvalue LONG_CONST(P_PGID) + */ +const P_PGID = UNKNOWN; +#endif +/* Linux specific idtype */ +#ifdef HAVE_LINUX_IDTYPES +/** + * @var int + * @cvalue LONG_CONST(P_PIDFD) + */ +const P_PIDFD = UNKNOWN; +#endif +/* NetBSD specific idtypes */ +#ifdef HAVE_NETBSD_IDTYPES +/** + * @var int + * @cvalue LONG_CONST(P_UID) + */ +const P_UID = UNKNOWN; +/** + * @var int + * @cvalue LONG_CONST(P_GID) + */ +const P_GID = UNKNOWN; +/** + * @var int + * @cvalue LONG_CONST(P_SID) + */ +const P_SID = UNKNOWN; +#endif +/* FreeBSD specific idtype */ +#ifdef HAVE_FREEBSD_IDTYPES +/** + * @var int + * @cvalue LONG_CONST(P_JAILID) + */ +const P_JAILID = UNKNOWN; +#endif +#endif /* Signal Constants */ @@ -927,6 +1003,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 {} +#endif + /** * @param int $status * @param array $resource_usage diff --git a/ext/pcntl/pcntl_arginfo.h b/ext/pcntl/pcntl_arginfo.h index 003f9cb5393d5..c919bbc1007bc 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: 775838bf2abbf32933f5cec6e4a85e07e8cea247 */ + * Stub hash: 71d0cbd8d2b1ae57d289ec421e9dcaa4040d857b */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_fork, 0, 0, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -11,6 +11,15 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_waitpid, 0, 2, IS_LONG, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(1, resource_usage, "[]") ZEND_END_ARG_INFO() +#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1 +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_waitid, 0, 0, _IS_BOOL, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, idtype, IS_LONG, 0, "P_ALL") + 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_END_ARG_INFO() +#endif + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pcntl_wait, 0, 1, IS_LONG, 0) ZEND_ARG_INFO(1, status) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0") @@ -170,6 +179,9 @@ ZEND_END_ARG_INFO() ZEND_FUNCTION(pcntl_fork); ZEND_FUNCTION(pcntl_waitpid); +#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1 +ZEND_FUNCTION(pcntl_waitid); +#endif ZEND_FUNCTION(pcntl_wait); ZEND_FUNCTION(pcntl_signal); ZEND_FUNCTION(pcntl_signal_get_handler); @@ -234,6 +246,9 @@ ZEND_FUNCTION(pcntl_setqos_class); static const zend_function_entry ext_functions[] = { ZEND_FE(pcntl_fork, arginfo_pcntl_fork) ZEND_FE(pcntl_waitpid, arginfo_pcntl_waitpid) +#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1 + ZEND_FE(pcntl_waitid, arginfo_pcntl_waitid) +#endif ZEND_FE(pcntl_wait, arginfo_pcntl_wait) ZEND_FE(pcntl_signal, arginfo_pcntl_signal) ZEND_FE(pcntl_signal_get_handler, arginfo_pcntl_signal_get_handler) @@ -314,6 +329,39 @@ static void register_pcntl_symbols(int module_number) #endif #if defined(HAVE_WCONTINUED) REGISTER_LONG_CONSTANT("WCONTINUED", LONG_CONST(WCONTINUED), CONST_PERSISTENT); +#endif +#if defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1 + REGISTER_LONG_CONSTANT("WEXITED", LONG_CONST(WEXITED), CONST_PERSISTENT); +#endif +#if defined (HAVE_DECL_WSTOPPED) && HAVE_DECL_WSTOPPED == 1 + REGISTER_LONG_CONSTANT("WSTOPPED", LONG_CONST(WSTOPPED), CONST_PERSISTENT); +#endif +#if defined (HAVE_DECL_WNOWAIT) && HAVE_DECL_WNOWAIT== 1 + REGISTER_LONG_CONSTANT("WNOWAIT", LONG_CONST(WNOWAIT), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_POSIX_IDTYPES) + REGISTER_LONG_CONSTANT("P_ALL", LONG_CONST(P_ALL), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_POSIX_IDTYPES) + REGISTER_LONG_CONSTANT("P_PID", LONG_CONST(P_PID), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_POSIX_IDTYPES) + REGISTER_LONG_CONSTANT("P_PGID", LONG_CONST(P_PGID), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_LINUX_IDTYPES) + REGISTER_LONG_CONSTANT("P_PIDFD", LONG_CONST(P_PIDFD), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_NETBSD_IDTYPES) + REGISTER_LONG_CONSTANT("P_UID", LONG_CONST(P_UID), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_NETBSD_IDTYPES) + REGISTER_LONG_CONSTANT("P_GID", LONG_CONST(P_GID), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_NETBSD_IDTYPES) + REGISTER_LONG_CONSTANT("P_SID", LONG_CONST(P_SID), CONST_PERSISTENT); +#endif +#if defined(HAVE_WAITID) && defined(HAVE_FREEBSD_IDTYPES) + REGISTER_LONG_CONSTANT("P_JAILID", LONG_CONST(P_JAILID), CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("SIG_IGN", LONG_CONST(SIG_IGN), CONST_PERSISTENT); REGISTER_LONG_CONSTANT("SIG_DFL", LONG_CONST(SIG_DFL), CONST_PERSISTENT); diff --git a/ext/pcntl/php_pcntl.h b/ext/pcntl/php_pcntl.h index d34771062be7b..f09ccadcd3cdb 100644 --- a/ext/pcntl/php_pcntl.h +++ b/ext/pcntl/php_pcntl.h @@ -17,7 +17,7 @@ #ifndef PHP_PCNTL_H #define PHP_PCNTL_H -#if defined(WCONTINUED) && defined(WIFCONTINUED) +#if defined(HAVE_DECL_WCONTINUED) && HAVE_DECL_WCONTINUED == 1 && defined(HAVE_WIFCONTINUED) && HAVE_WIFCONTINUED == 1 #define HAVE_WCONTINUED 1 #endif diff --git a/ext/pcntl/tests/pcntl_waitid.phpt b/ext/pcntl/tests/pcntl_waitid.phpt new file mode 100644 index 0000000000000..b00f26f81fa2e --- /dev/null +++ b/ext/pcntl/tests/pcntl_waitid.phpt @@ -0,0 +1,41 @@ +--TEST-- +pcntl_waitid() +--EXTENSIONS-- +pcntl +posix +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +bool(false) +bool(true) +bool(true) +bool(true) +bool(true) +int(42)