mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Use PDEATHSIG to kill cli-server workers if parent exists
Closes GH-9476
This commit is contained in:
parent
c200623f28
commit
ecc3fc180f
8 changed files with 114 additions and 32 deletions
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
#include "zend_portability.h"
|
#include "zend_portability.h"
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef HAVE_PRCTL
|
||||||
# include <sys/prctl.h>
|
# include <sys/prctl.h>
|
||||||
|
|
||||||
/* fallback definitions if our libc is older than the kernel */
|
/* fallback definitions if our libc is older than the kernel */
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
# ifndef PR_SET_VMA_ANON_NAME
|
# ifndef PR_SET_VMA_ANON_NAME
|
||||||
# define PR_SET_VMA_ANON_NAME 0
|
# define PR_SET_VMA_ANON_NAME 0
|
||||||
# endif
|
# endif
|
||||||
#endif // __linux__
|
#endif // HAVE_PRCTL
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a name for the specified memory area.
|
* Set a name for the specified memory area.
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
*/
|
*/
|
||||||
static zend_always_inline void zend_mmap_set_name(const void *start, size_t len, const char *name)
|
static zend_always_inline void zend_mmap_set_name(const void *start, size_t len, const char *name)
|
||||||
{
|
{
|
||||||
#ifdef __linux__
|
#ifdef HAVE_PRCTL
|
||||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)start, len, (unsigned long)name);
|
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)start, len, (unsigned long)name);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
26
build/php.m4
26
build/php.m4
|
@ -2748,3 +2748,29 @@ AC_DEFUN([PHP_PATCH_CONFIG_HEADERS], [
|
||||||
$SED -e 's/^#undef PACKAGE_[^ ]*/\/\* & \*\//g' < $srcdir/$1 \
|
$SED -e 's/^#undef PACKAGE_[^ ]*/\/\* & \*\//g' < $srcdir/$1 \
|
||||||
> $srcdir/$1.tmp && mv $srcdir/$1.tmp $srcdir/$1
|
> $srcdir/$1.tmp && mv $srcdir/$1.tmp $srcdir/$1
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl Check if we have prctl
|
||||||
|
AC_DEFUN([PHP_CHECK_PRCTL],
|
||||||
|
[
|
||||||
|
AC_MSG_CHECKING([for prctl])
|
||||||
|
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/prctl.h>]], [[prctl(0, 0, 0, 0, 0);]])], [
|
||||||
|
AC_DEFINE([HAVE_PRCTL], 1, [do we have prctl?])
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Check if we have procctl
|
||||||
|
AC_DEFUN([PHP_CHECK_PROCCTL],
|
||||||
|
[
|
||||||
|
AC_MSG_CHECKING([for procctl])
|
||||||
|
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/procctl.h>]], [[procctl(0, 0, 0, 0);]])], [
|
||||||
|
AC_DEFINE([HAVE_PROCCTL], 1, [do we have procctl?])
|
||||||
|
AC_MSG_RESULT([yes])
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT([no])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
|
@ -510,6 +510,10 @@ dnl Check __builtin_cpu_init
|
||||||
PHP_CHECK_BUILTIN_CPU_INIT
|
PHP_CHECK_BUILTIN_CPU_INIT
|
||||||
dnl Check __builtin_cpu_supports
|
dnl Check __builtin_cpu_supports
|
||||||
PHP_CHECK_BUILTIN_CPU_SUPPORTS
|
PHP_CHECK_BUILTIN_CPU_SUPPORTS
|
||||||
|
dnl Check prctl
|
||||||
|
PHP_CHECK_PRCTL
|
||||||
|
dnl Check procctl
|
||||||
|
PHP_CHECK_PROCCTL
|
||||||
|
|
||||||
dnl Check for __alignof__ support in the compiler
|
dnl Check for __alignof__ support in the compiler
|
||||||
AC_CACHE_CHECK(whether the compiler supports __alignof__, ac_cv_alignof_exists,[
|
AC_CACHE_CHECK(whether the compiler supports __alignof__, ac_cv_alignof_exists,[
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef PHP_WIN32
|
#ifdef PHP_WIN32
|
||||||
# include <process.h>
|
# include <process.h>
|
||||||
|
@ -49,6 +50,14 @@
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PRCTL
|
||||||
|
# include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PROCCTL
|
||||||
|
# include <sys/procctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "SAPI.h"
|
#include "SAPI.h"
|
||||||
#include "php.h"
|
#include "php.h"
|
||||||
#include "php_ini.h"
|
#include "php_ini.h"
|
||||||
|
@ -2432,6 +2441,24 @@ static char *php_cli_server_parse_addr(const char *addr, int *pport) {
|
||||||
return pestrndup(addr, end - addr, 1);
|
return pestrndup(addr, end - addr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(HAVE_PRCTL) || defined(HAVE_PROCCTL)
|
||||||
|
static void php_cli_server_worker_install_pdeathsig(void)
|
||||||
|
{
|
||||||
|
// Ignore failure to register PDEATHSIG, it's not available on all platforms anyway
|
||||||
|
#if defined(HAVE_PRCTL)
|
||||||
|
prctl(PR_SET_PDEATHSIG, SIGTERM);
|
||||||
|
#elif defined(HAVE_PROCCTL)
|
||||||
|
int signal = SIGTERM;
|
||||||
|
procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signal);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check if parent has exited just after the fork
|
||||||
|
if (getppid() != php_cli_server_master) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void php_cli_server_startup_workers(void) {
|
static void php_cli_server_startup_workers(void) {
|
||||||
char *workers = getenv("PHP_CLI_SERVER_WORKERS");
|
char *workers = getenv("PHP_CLI_SERVER_WORKERS");
|
||||||
if (!workers) {
|
if (!workers) {
|
||||||
|
@ -2459,6 +2486,9 @@ static void php_cli_server_startup_workers(void) {
|
||||||
php_cli_server_worker + 1;
|
php_cli_server_worker + 1;
|
||||||
return;
|
return;
|
||||||
} else if (pid == 0) {
|
} else if (pid == 0) {
|
||||||
|
#if defined(HAVE_PRCTL) || defined(HAVE_PROCCTL)
|
||||||
|
php_cli_server_worker_install_pdeathsig();
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
php_cli_server_workers[php_cli_server_worker] = pid;
|
php_cli_server_workers[php_cli_server_worker] = pid;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
class CliServerInfo {
|
class CliServerInfo {
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $docRoot,
|
public string $docRoot,
|
||||||
|
public $processHandle,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +114,7 @@ function php_cli_server_start(
|
||||||
define("PHP_CLI_SERVER_PORT", $port);
|
define("PHP_CLI_SERVER_PORT", $port);
|
||||||
define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT);
|
define("PHP_CLI_SERVER_ADDRESS", PHP_CLI_SERVER_HOSTNAME.":".PHP_CLI_SERVER_PORT);
|
||||||
|
|
||||||
return new CliServerInfo($doc_root);
|
return new CliServerInfo($doc_root, $handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
function php_cli_server_connect() {
|
function php_cli_server_connect() {
|
||||||
|
|
46
sapi/cli/tests/php_cli_server_pdeathsig.phpt
Normal file
46
sapi/cli/tests/php_cli_server_pdeathsig.phpt
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
--TEST--
|
||||||
|
Killing server should terminate all worker processes
|
||||||
|
--ENV--
|
||||||
|
PHP_CLI_SERVER_WORKERS=2
|
||||||
|
--SKIPIF--
|
||||||
|
<?php
|
||||||
|
include "skipif.inc";
|
||||||
|
if (!(str_contains(PHP_OS, 'Linux') || str_contains(PHP_OS, 'FreeBSD'))) {
|
||||||
|
die('skip PDEATHSIG is only supported on Linux and FreeBSD');
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
|
function split_words(?string $lines): array {
|
||||||
|
return preg_split('(\s)', trim($lines ?? ''), flags: PREG_SPLIT_NO_EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_workers_by_ppid(string $ppid) {
|
||||||
|
return split_words(shell_exec('pgrep -P ' . $ppid));
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_workers_by_pids(array $pids) {
|
||||||
|
return split_words(shell_exec('ps -o pid= -p ' . join(',', $pids)));
|
||||||
|
}
|
||||||
|
|
||||||
|
include "php_cli_server.inc";
|
||||||
|
$cliServerInfo = php_cli_server_start('');
|
||||||
|
|
||||||
|
$master = proc_get_status($cliServerInfo->processHandle)['pid'];
|
||||||
|
$workers = find_workers_by_ppid($master);
|
||||||
|
if (count($workers) === 0) {
|
||||||
|
throw new \Exception('Could not find worker pids');
|
||||||
|
}
|
||||||
|
|
||||||
|
proc_terminate($cliServerInfo->processHandle, 9); // SIGKILL
|
||||||
|
|
||||||
|
$workers = find_workers_by_pids($workers);
|
||||||
|
if (count($workers) !== 0) {
|
||||||
|
throw new \Exception('Workers were not properly terminated');
|
||||||
|
}
|
||||||
|
|
||||||
|
echo 'Done';
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
Done
|
|
@ -13,30 +13,6 @@ AC_DEFUN([AC_FPM_STDLIBS],
|
||||||
AC_SEARCH_LIBS(inet_addr, nsl)
|
AC_SEARCH_LIBS(inet_addr, nsl)
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([AC_FPM_PRCTL],
|
|
||||||
[
|
|
||||||
AC_MSG_CHECKING([for prctl])
|
|
||||||
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/prctl.h>]], [[prctl(0, 0, 0, 0, 0);]])], [
|
|
||||||
AC_DEFINE([HAVE_PRCTL], 1, [do we have prctl?])
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
], [
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_DEFUN([AC_FPM_PROCCTL],
|
|
||||||
[
|
|
||||||
AC_MSG_CHECKING([for procctl])
|
|
||||||
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <sys/procctl.h>]], [[procctl(0, 0, 0, 0);]])], [
|
|
||||||
AC_DEFINE([HAVE_PROCCTL], 1, [do we have procctl?])
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
], [
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
])
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_DEFUN([AC_FPM_SETPFLAGS],
|
AC_DEFUN([AC_FPM_SETPFLAGS],
|
||||||
[
|
[
|
||||||
AC_MSG_CHECKING([for setpflags])
|
AC_MSG_CHECKING([for setpflags])
|
||||||
|
@ -530,8 +506,6 @@ if test "$PHP_FPM" != "no"; then
|
||||||
AC_MSG_RESULT($PHP_FPM)
|
AC_MSG_RESULT($PHP_FPM)
|
||||||
|
|
||||||
AC_FPM_STDLIBS
|
AC_FPM_STDLIBS
|
||||||
AC_FPM_PRCTL
|
|
||||||
AC_FPM_PROCCTL
|
|
||||||
AC_FPM_SETPFLAGS
|
AC_FPM_SETPFLAGS
|
||||||
AC_FPM_CLOCK
|
AC_FPM_CLOCK
|
||||||
AC_FPM_TRACE
|
AC_FPM_TRACE
|
||||||
|
|
|
@ -74,10 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <php_config.h>
|
||||||
|
|
||||||
#include "lsapilib.h"
|
#include "lsapilib.h"
|
||||||
|
|
||||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
|
#ifdef HAVE_PRCTL
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -381,7 +382,7 @@ static void lsapi_enable_core_dump(void)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
|
#ifdef HAVE_PRCTL
|
||||||
if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
|
if (prctl(PR_SET_DUMPABLE, s_enable_core_dump,0,0,0) == -1)
|
||||||
perror( "prctl: Failed to set dumpable, "
|
perror( "prctl: Failed to set dumpable, "
|
||||||
"core dump may not be available!");
|
"core dump may not be available!");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue