Skip to content

Commit c2fd071

Browse files
vrzadevnexen
authored andcommitted
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
1 parent af29403 commit c2fd071

File tree

8 files changed

+244
-4
lines changed

8 files changed

+244
-4
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ PHP NEWS
190190
. Added pcntl_getqos_class/pcntl_setqos_class for macOs. (David Carlier)
191191
. Added SIGCKPT/SIGCKPTEXIT constants for DragonFlyBSD. (David Carlier)
192192
. Added FreeBSD's SIGTRAP handling to pcntl_siginfo_to_zval. (David Carlier)
193+
. Added POSIX pcntl_waitid. (Vladimir Vrzić)
193194

194195
- PCRE:
195196
. Upgrade bundled pcre2lib to version 10.43. (nielsdos)

UPGRADING

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,8 @@ PHP 8.4 UPGRADE NOTES
594594
. Added pcntl_getcpu to get the cpu id from where the current process runs.
595595
. Added pcntl_getqos_class to get the QoS level (aka performance and related
596596
energy consumption) of the current process and pcntl_setqos_class to set it.
597+
. Added pcntl_waitid to obtain status information pertaining to termination, stop,
598+
and/or continue events in one of the caller's child processes.
597599

598600
- PDO_PGSQL:
599601
. Added Pdo\Pgsql::setNoticeCallback() to allow a callback to be triggered on
@@ -780,7 +782,18 @@ PHP 8.4 UPGRADE NOTES
780782
. QosClass::Utility (macOs only).
781783
. SIGCKPT (DragonFlyBSD only).
782784
. SIGCKPTEXIT (DragonFlyBSD only).
783-
785+
. WEXITED.
786+
. WSTOPPED.
787+
. WNOWAIT.
788+
. P_ALL.
789+
. P_PID.
790+
. P_PGID.
791+
. P_PIDFD (Linux only).
792+
. P_UID (NetBSD only).
793+
. P_GID (NetBSD only).
794+
. P_SID (NetBSD only).
795+
. P_JAILID (FreeBSD only).
796+
784797
- Standard:
785798
. PHP_ROUND_CEILING.
786799
. PHP_ROUND_FLOOR.

ext/pcntl/config.m4

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,16 @@ if test "$PHP_PCNTL" != "no"; then
2424
unshare
2525
wait3
2626
wait4
27+
waitid
2728
]))
2829

30+
AC_CHECK_FUNCS([WIFCONTINUED],,
31+
[AC_CHECK_DECL([WIFCONTINUED], [AC_DEFINE([HAVE_WIFCONTINUED], [1])],,
32+
[#include <sys/wait.h>])])
33+
34+
AC_CHECK_DECLS([WCONTINUED, WEXITED, WSTOPPED, WNOWAIT, P_ALL, P_PIDFD, P_UID, P_JAILID],,,
35+
[#include <sys/wait.h>])
36+
2937
dnl if unsupported, -1 means automatically ENOSYS in this context
3038
AC_CACHE_CHECK([if sched_getcpu is supported], [php_cv_func_sched_getcpu],
3139
[AC_RUN_IFELSE([AC_LANG_SOURCE([

ext/pcntl/pcntl.c

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929

3030
#include "php.h"
3131
#include "ext/standard/info.h"
32-
#include "php_pcntl.h"
3332
#include "php_signal.h"
3433
#include "php_ticks.h"
3534
#include "zend_fibers.h"
@@ -40,6 +39,22 @@
4039
#include <sys/resource.h>
4140
#endif
4241

42+
#ifdef HAVE_WAITID
43+
#if defined (HAVE_DECL_P_ALL) && HAVE_DECL_P_ALL == 1
44+
#define HAVE_POSIX_IDTYPES 1
45+
#endif
46+
#if defined (HAVE_DECL_P_PIDFD) && HAVE_DECL_P_PIDFD == 1
47+
#define HAVE_LINUX_IDTYPES 1
48+
#endif
49+
#if defined (HAVE_DECL_P_UID) && HAVE_DECL_P_UID == 1
50+
#define HAVE_NETBSD_IDTYPES 1
51+
#endif
52+
#if defined (HAVE_DECL_P_JAILID) && HAVE_DECL_P_JAILID == 1
53+
#define HAVE_FREEBSD_IDTYPES 1
54+
#endif
55+
#endif
56+
57+
#include "php_pcntl.h"
4358
#include <errno.h>
4459
#if defined(HAVE_UNSHARE) || defined(HAVE_SCHED_SETAFFINITY) || defined(HAVE_SCHED_GETCPU)
4560
#include <sched.h>
@@ -385,6 +400,39 @@ PHP_FUNCTION(pcntl_waitpid)
385400
}
386401
/* }}} */
387402

403+
#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1
404+
PHP_FUNCTION(pcntl_waitid)
405+
{
406+
zend_long idtype = P_ALL;
407+
zend_long id = 0;
408+
bool id_is_null = 1;
409+
zval *user_siginfo = NULL;
410+
zend_long options = WEXITED;
411+
412+
ZEND_PARSE_PARAMETERS_START(0, 4)
413+
Z_PARAM_OPTIONAL
414+
Z_PARAM_LONG(idtype)
415+
Z_PARAM_LONG_OR_NULL(id, id_is_null)
416+
Z_PARAM_ZVAL(user_siginfo)
417+
Z_PARAM_LONG(options)
418+
ZEND_PARSE_PARAMETERS_END();
419+
420+
errno = 0;
421+
siginfo_t siginfo;
422+
423+
int status = waitid((idtype_t) idtype, (id_t) id, &siginfo, (int) options);
424+
425+
if (status == -1) {
426+
PCNTL_G(last_error) = errno;
427+
RETURN_FALSE;
428+
}
429+
430+
pcntl_siginfo_to_zval(SIGCHLD, &siginfo, user_siginfo);
431+
432+
RETURN_TRUE;
433+
}
434+
#endif
435+
388436
/* {{{ Waits on or returns the status of a forked child as defined by the waitpid() system call */
389437
PHP_FUNCTION(pcntl_wait)
390438
{

ext/pcntl/pcntl.stub.php

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,82 @@
2525
*/
2626
const WCONTINUED = UNKNOWN;
2727
#endif
28+
#if defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1
29+
/**
30+
* @var int
31+
* @cvalue LONG_CONST(WEXITED)
32+
*/
33+
const WEXITED = UNKNOWN;
34+
#endif
35+
#if defined (HAVE_DECL_WSTOPPED) && HAVE_DECL_WSTOPPED == 1
36+
/**
37+
* @var int
38+
* @cvalue LONG_CONST(WSTOPPED)
39+
*/
40+
const WSTOPPED = UNKNOWN;
41+
#endif
42+
#if defined (HAVE_DECL_WNOWAIT) && HAVE_DECL_WNOWAIT== 1
43+
/**
44+
* @var int
45+
* @cvalue LONG_CONST(WNOWAIT)
46+
*/
47+
const WNOWAIT = UNKNOWN;
48+
#endif
49+
50+
#ifdef HAVE_WAITID
51+
/* First argument to waitid */
52+
#ifdef HAVE_POSIX_IDTYPES
53+
/**
54+
* @var int
55+
* @cvalue LONG_CONST(P_ALL)
56+
*/
57+
const P_ALL = UNKNOWN;
58+
/**
59+
* @var int
60+
* @cvalue LONG_CONST(P_PID)
61+
*/
62+
const P_PID = UNKNOWN;
63+
/**
64+
* @var int
65+
* @cvalue LONG_CONST(P_PGID)
66+
*/
67+
const P_PGID = UNKNOWN;
68+
#endif
69+
/* Linux specific idtype */
70+
#ifdef HAVE_LINUX_IDTYPES
71+
/**
72+
* @var int
73+
* @cvalue LONG_CONST(P_PIDFD)
74+
*/
75+
const P_PIDFD = UNKNOWN;
76+
#endif
77+
/* NetBSD specific idtypes */
78+
#ifdef HAVE_NETBSD_IDTYPES
79+
/**
80+
* @var int
81+
* @cvalue LONG_CONST(P_UID)
82+
*/
83+
const P_UID = UNKNOWN;
84+
/**
85+
* @var int
86+
* @cvalue LONG_CONST(P_GID)
87+
*/
88+
const P_GID = UNKNOWN;
89+
/**
90+
* @var int
91+
* @cvalue LONG_CONST(P_SID)
92+
*/
93+
const P_SID = UNKNOWN;
94+
#endif
95+
/* FreeBSD specific idtype */
96+
#ifdef HAVE_FREEBSD_IDTYPES
97+
/**
98+
* @var int
99+
* @cvalue LONG_CONST(P_JAILID)
100+
*/
101+
const P_JAILID = UNKNOWN;
102+
#endif
103+
#endif
28104

29105
/* Signal Constants */
30106

@@ -927,6 +1003,11 @@ function pcntl_fork(): int {}
9271003
*/
9281004
function pcntl_waitpid(int $process_id, &$status, int $flags = 0, &$resource_usage = []): int {}
9291005

1006+
#if defined (HAVE_WAITID) && defined (HAVE_POSIX_IDTYPES) && defined (HAVE_DECL_WEXITED) && HAVE_DECL_WEXITED == 1
1007+
/** @param array $info */
1008+
function pcntl_waitid(int $idtype = P_ALL, ?int $id = null, &$info = [], int $flags = WEXITED): bool {}
1009+
#endif
1010+
9301011
/**
9311012
* @param int $status
9321013
* @param array $resource_usage

ext/pcntl/pcntl_arginfo.h

Lines changed: 49 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/pcntl/php_pcntl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#ifndef PHP_PCNTL_H
1818
#define PHP_PCNTL_H
1919

20-
#if defined(WCONTINUED) && defined(WIFCONTINUED)
20+
#if defined(HAVE_DECL_WCONTINUED) && HAVE_DECL_WCONTINUED == 1 && defined(HAVE_WIFCONTINUED) && HAVE_WIFCONTINUED == 1
2121
#define HAVE_WCONTINUED 1
2222
#endif
2323

ext/pcntl/tests/pcntl_waitid.phpt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
pcntl_waitid()
3+
--EXTENSIONS--
4+
pcntl
5+
posix
6+
--SKIPIF--
7+
<?php
8+
if (!function_exists('pcntl_waitid')) die('skip pcntl_waitid unavailable');
9+
?>
10+
--FILE--
11+
<?php
12+
$pid = pcntl_fork();
13+
if ($pid == -1) {
14+
die("failed");
15+
} else if ($pid) {
16+
// invalid flags
17+
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, 0));
18+
var_dump(pcntl_get_last_error() == PCNTL_EINVAL);
19+
20+
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WSTOPPED));
21+
posix_kill($pid, SIGCONT);
22+
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WCONTINUED));
23+
posix_kill($pid, SIGUSR1);
24+
var_dump(pcntl_waitid(P_PID, $pid, $siginfo, WEXITED));
25+
var_dump($siginfo["status"]);
26+
} else {
27+
pcntl_signal(SIGUSR1, function ($_signo, $_siginfo) { exit(42); });
28+
posix_kill(posix_getpid(), SIGSTOP);
29+
pcntl_signal_dispatch();
30+
sleep(42);
31+
pcntl_signal_dispatch();
32+
exit(6);
33+
}
34+
?>
35+
--EXPECTF--
36+
bool(false)
37+
bool(true)
38+
bool(true)
39+
bool(true)
40+
bool(true)
41+
int(42)

0 commit comments

Comments
 (0)