1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

ext/pcntl: Added new function pcntl_waitid

to obtain status information pertaining termination, stop, and/or
continue events in one the caller's child processes.

close GH-14617
This commit is contained in:
Vladimir Vrzić
2024-06-20 14:47:27 +02:00
committed by David Carlier
parent af29403ea0
commit c2fd071db7
8 changed files with 244 additions and 4 deletions

1
NEWS
View File

@@ -190,6 +190,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)

View File

@@ -594,6 +594,8 @@ PHP 8.4 UPGRADE NOTES
. Added pcntl_getcpu to get the cpu id from where the current process runs.
. Added pcntl_getqos_class to get the QoS level (aka performance and related
energy consumption) of the current process and pcntl_setqos_class to set it.
. Added pcntl_waitid to obtain status information pertaining to termination, stop,
and/or continue events in one of the caller's child processes.
- PDO_PGSQL:
. Added Pdo\Pgsql::setNoticeCallback() to allow a callback to be triggered on
@@ -780,7 +782,18 @@ PHP 8.4 UPGRADE NOTES
. QosClass::Utility (macOs only).
. SIGCKPT (DragonFlyBSD only).
. SIGCKPTEXIT (DragonFlyBSD only).
. WEXITED.
. WSTOPPED.
. WNOWAIT.
. P_ALL.
. P_PID.
. P_PGID.
. P_PIDFD (Linux only).
. P_UID (NetBSD only).
. P_GID (NetBSD only).
. P_SID (NetBSD only).
. P_JAILID (FreeBSD only).
- Standard:
. PHP_ROUND_CEILING.
. PHP_ROUND_FLOOR.

View File

@@ -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 <sys/wait.h>])])
AC_CHECK_DECLS([WCONTINUED, WEXITED, WSTOPPED, WNOWAIT, P_ALL, P_PIDFD, P_UID, P_JAILID],,,
[#include <sys/wait.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([

View File

@@ -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 <sys/resource.h>
#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 <errno.h>
#if defined(HAVE_UNSHARE) || defined(HAVE_SCHED_SETAFFINITY) || defined(HAVE_SCHED_GETCPU)
#include <sched.h>
@@ -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)
{

View File

@@ -25,6 +25,82 @@ const WUNTRACED = UNKNOWN;
*/
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

View File

@@ -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);

View File

@@ -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

View File

@@ -0,0 +1,41 @@
--TEST--
pcntl_waitid()
--EXTENSIONS--
pcntl
posix
--SKIPIF--
<?php
if (!function_exists('pcntl_waitid')) die('skip pcntl_waitid unavailable');
?>
--FILE--
<?php
$pid = pcntl_fork();
if ($pid == -1) {
die("failed");
} else if ($pid) {
// invalid flags
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, 0));
var_dump(pcntl_get_last_error() == PCNTL_EINVAL);
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WSTOPPED));
posix_kill($pid, SIGCONT);
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WCONTINUED));
posix_kill($pid, SIGUSR1);
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WEXITED));
var_dump($siginfo["status"]);
} else {
pcntl_signal(SIGUSR1, function ($_signo, $_siginfo) { exit(42); });
posix_kill(posix_getpid(), SIGSTOP);
pcntl_signal_dispatch();
sleep(42);
pcntl_signal_dispatch();
exit(6);
}
?>
--EXPECTF--
bool(false)
bool(true)
bool(true)
bool(true)
bool(true)
int(42)