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"
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef HAVE_PRCTL
|
||||
# include <sys/prctl.h>
|
||||
|
||||
/* fallback definitions if our libc is older than the kernel */
|
||||
|
@ -27,7 +27,7 @@
|
|||
# ifndef PR_SET_VMA_ANON_NAME
|
||||
# define PR_SET_VMA_ANON_NAME 0
|
||||
# endif
|
||||
#endif // __linux__
|
||||
#endif // HAVE_PRCTL
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
#ifdef __linux__
|
||||
#ifdef HAVE_PRCTL
|
||||
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)start, len, (unsigned long)name);
|
||||
#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 \
|
||||
> $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
|
||||
dnl 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
|
||||
AC_CACHE_CHECK(whether the compiler supports __alignof__, ac_cv_alignof_exists,[
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
|
||||
#ifdef PHP_WIN32
|
||||
# include <process.h>
|
||||
|
@ -49,6 +50,14 @@
|
|||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PRCTL
|
||||
# include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PROCCTL
|
||||
# include <sys/procctl.h>
|
||||
#endif
|
||||
|
||||
#include "SAPI.h"
|
||||
#include "php.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);
|
||||
}
|
||||
|
||||
#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) {
|
||||
char *workers = getenv("PHP_CLI_SERVER_WORKERS");
|
||||
if (!workers) {
|
||||
|
@ -2459,6 +2486,9 @@ static void php_cli_server_startup_workers(void) {
|
|||
php_cli_server_worker + 1;
|
||||
return;
|
||||
} else if (pid == 0) {
|
||||
#if defined(HAVE_PRCTL) || defined(HAVE_PROCCTL)
|
||||
php_cli_server_worker_install_pdeathsig();
|
||||
#endif
|
||||
return;
|
||||
} else {
|
||||
php_cli_server_workers[php_cli_server_worker] = pid;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
class CliServerInfo {
|
||||
public function __construct(
|
||||
public string $docRoot,
|
||||
public $processHandle,
|
||||
) {}
|
||||
}
|
||||
|
||||
|
@ -113,7 +114,7 @@ function php_cli_server_start(
|
|||
define("PHP_CLI_SERVER_PORT", $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() {
|
||||
|
|
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_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_MSG_CHECKING([for setpflags])
|
||||
|
@ -530,8 +506,6 @@ if test "$PHP_FPM" != "no"; then
|
|||
AC_MSG_RESULT($PHP_FPM)
|
||||
|
||||
AC_FPM_STDLIBS
|
||||
AC_FPM_PRCTL
|
||||
AC_FPM_PROCCTL
|
||||
AC_FPM_SETPFLAGS
|
||||
AC_FPM_CLOCK
|
||||
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/tcp.h>
|
||||
#include <sys/un.h>
|
||||
#include <php_config.h>
|
||||
|
||||
#include "lsapilib.h"
|
||||
|
||||
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
|
||||
#ifdef HAVE_PRCTL
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
|
||||
|
@ -381,7 +382,7 @@ static void lsapi_enable_core_dump(void)
|
|||
|
||||
#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)
|
||||
perror( "prctl: Failed to set dumpable, "
|
||||
"core dump may not be available!");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue