-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Do not let PHP-FPM children miss SIGTERM, SIGQUIT #4836
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
8ac3486
Do not let PHP-FPM children miss SIGTERM, SIGQUIT
plmnikulin 82c0c16
Add PHP-FPM test (slow) for reload Bug #76601
plmnikulin 278f57f
Signal list internal to `fpm_signals_init_mask()`
plmnikulin 067cf2e
Do not use memcpy for sigset_t manipulation in FPM
plmnikulin 8aad009
Reword comment in FPM sig_handler()
plmnikulin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1572,11 +1572,7 @@ int main(int argc, char *argv[]) | |
does that for us! [email protected] | ||
20000419 */ | ||
|
||
/* Subset of signals from fpm_signals_init_main() to avoid unexpected death during early init | ||
or during reload just after execvp() or fork */ | ||
int init_signal_array[] = { SIGUSR1, SIGUSR2, SIGCHLD }; | ||
if (0 > fpm_signals_init_mask(init_signal_array, sizeof(init_signal_array)/sizeof(init_signal_array[0])) || | ||
0 > fpm_signals_block()) { | ||
if (0 > fpm_signals_init_mask() || 0 > fpm_signals_block()) { | ||
zlog(ZLOG_WARNING, "Could die in the case of too early reload signal"); | ||
} | ||
zlog(ZLOG_DEBUG, "Blocked some signals"); | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
--TEST-- | ||
FPM: bug76601 children should not ignore signals during concurrent reloads | ||
--SKIPIF-- | ||
<?php | ||
include "skipif.inc"; | ||
if (getenv("SKIP_SLOW_TESTS")) die("skip slow test"); | ||
?> | ||
--FILE-- | ||
<?php | ||
|
||
require_once "tester.inc"; | ||
|
||
$cfg = <<<EOT | ||
[global] | ||
error_log = {{FILE:LOG}} | ||
pid = {{FILE:PID}} | ||
; some value twice greater than tester->getLogLines() timeout | ||
process_control_timeout=10 | ||
[unconfined] | ||
listen = {{ADDR}} | ||
; spawn children immediately after reload | ||
pm = static | ||
pm.max_children = 10 | ||
EOT; | ||
|
||
$code = <<<EOT | ||
<?php | ||
/* empty */ | ||
EOT; | ||
|
||
/* | ||
* If a child miss SIGQUIT then reload process should stuck | ||
* for at least process_control_timeout that is set greater | ||
* than timout in log reading functions. | ||
* | ||
* Alternative way is to set log_level=debug and filter result of | ||
* $tester->getLogLines(2000) for lines containing SIGKILL | ||
* | ||
* [22-Oct-2019 03:28:19.532703] DEBUG: pid 21315, fpm_pctl_kill_all(), line 161: [pool unconfined] sending signal 9 SIGKILL to child 21337 | ||
* [22-Oct-2019 03:28:19.533471] DEBUG: pid 21315, fpm_children_bury(), line 259: [pool unconfined] child 21337 exited on signal 9 (SIGKILL) after 1.003055 seconds from start | ||
* | ||
* but it has less probability of failure detection. Additionally it requires more | ||
* $tester->expectLogNotice() around last reload due to presence of debug messages. | ||
*/ | ||
|
||
$tester = new FPM\Tester($cfg, $code); | ||
$tester->start(); | ||
$tester->expectLogStartNotices(); | ||
|
||
/* Vary interval between concurrent reload requests | ||
since performance of test instance is not known in advance */ | ||
$max_interval = 25000; | ||
$step = 1000; | ||
$pid = $tester->getPid(); | ||
for ($interval = 0; $interval < $max_interval; $interval += $step) { | ||
exec("kill -USR2 $pid", $out, $killExitCode); | ||
if ($killExitCode) { | ||
echo "ERROR: master process is dead\n"; | ||
break; | ||
} | ||
usleep($interval); | ||
} | ||
echo "Reached interval $interval us with $step us steps\n"; | ||
$tester->expectLogNotice('Reloading in progress ...'); | ||
/* Consume mix of 'Reloading in progress ...' and 'reloading: .*' */ | ||
$skipped = $tester->getLogLines(2000); | ||
|
||
$tester->signal('USR2'); | ||
$tester->expectLogNotice('Reloading in progress ...'); | ||
/* When a child ignores SIGQUIT, the following expectation fails due to timeout. */ | ||
if (!$tester->expectLogNotice('reloading: .*')) { | ||
/* for troubleshooting */ | ||
echo "Skipped messages\n"; | ||
echo implode('', $skipped); | ||
} | ||
$tester->expectLogNotice('using inherited socket fd=\d+, "127.0.0.1:\d+"'); | ||
$tester->expectLogStartNotices(); | ||
|
||
$tester->terminate(); | ||
$tester->expectLogTerminatingNotices(); | ||
$tester->close(); | ||
|
||
?> | ||
Done | ||
--EXPECT-- | ||
Reached interval 25000 us with 1000 us steps | ||
Done | ||
--CLEAN-- | ||
<?php | ||
require_once "tester.inc"; | ||
FPM\Tester::clean(); | ||
?> |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the actually the reason specify one part (block_sigset) from parameter provided in fpm_main.c and another part (child_block_sigset extra signals) specified directly in this function? I think we should either have everything in the parameters (meaning extra child signals to block array paramter) or just have everything defined in fpm_signals which might make more sense.