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:
committed by
David Carlier
parent
af29403ea0
commit
c2fd071db7
1
NEWS
1
NEWS
@@ -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)
|
||||
|
||||
15
UPGRADING
15
UPGRADING
@@ -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.
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
50
ext/pcntl/pcntl_arginfo.h
generated
50
ext/pcntl/pcntl_arginfo.h
generated
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
41
ext/pcntl/tests/pcntl_waitid.phpt
Normal file
41
ext/pcntl/tests/pcntl_waitid.phpt
Normal 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)
|
||||
Reference in New Issue
Block a user