Bug #73783 [Com]: pcntl_signal() issue

From: Date: Tue, 20 Dec 2016 15:41:18 +0000
Subject: Bug #73783 [Com]: pcntl_signal() issue
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-206160@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=73783&edit=1 ID: 73783 Comment by: dave at mudsite dot com Reported by: zorg at razza dot org Summary: pcntl_signal() issue Status: Open Type: Bug Package: PCNTL related Operating System: Ubuntu 16.04.1 LTS PHP Version: 7.1.0 Block user comment: N Private report: N New Comment: I would assume as much, I wasn't directly able to replicate the <defunct> process. I tried on both my Debian setup & MacOS 10.12, which both lack the <defunct> but do both sleep correctly with the fix in place. The output I get with PHP 7.1, and my fix are as follows: dwalker@linux:~/src/php PHP-7.1 › time sapi/cli/php e.php && ps aux | grep defunc Parent Child Dying After Sleep real 0m0.022s user 0m0.004s sys 0m0.016s dwalker 24037 0.0 0.0 12784 940 pts/3 S+ 08:38 0:00 grep --color=auto defunc dwalker@linux:~/src/php fix-73783 › time sapi/cli/php e.php && ps aux | grep defunc Parent Child Dying After Sleep real 0m10.015s user 0m0.012s sys 0m0.004s dwalker 16683 0.0 0.0 12784 900 pts/3 S+ 08:37 0:00 grep --color=auto defunc Previous Comments: ------------------------------------------------------------------------ [2016-12-20 08:15:22] zorg at razza dot org Would this also fix the issue where pcntl_signal(SIGCHLD, SIG_IGN) no longer stops <defunct> threads from remaining until the main process has ended? In 7.0 threads would exit cleanly, but since upgrading to 7.1 they all sit as <defunct> now. ------------------------------------------------------------------------ [2016-12-19 20:54:16] dave at mudsite dot com This bug exists because ZEND_SIGNALS was defaulted to "yes" with PHP 7.1. The problem with this is that sleep() will sleep for the number of seconds, OR, is interrupted by a signal that is not ignored. With your test script with pcntl_signal(SIGCHLD, SIG_IGN), you're instructing PHP to ignore the end of a child. However, ZEND_SIGNALS, zend_sigaction() sets the set handler into the SIGG(handlers), but, will set the actual signal handler to zend_signal_handler_defer, which is not SIG_IGN. As such, during the sleeping, when a SIGCHLD is raised, sleep bails because it is not "ignored" at the system level, and ends up calling zend_signal_handler_defer which will not process the signal. I believe a safe fix would be to in zend_sigaction, only set the defer handler IF the incoming sigact's handler is not SIG_IGN. Will make a PR and see if it's acceptable or not. ------------------------------------------------------------------------ [2016-12-19 10:30:51] zorg at razza dot org Sorry, the test script is incorrect. It should be: pcntl_signal(SIGCHLD, SIG_IGN); $pid = @pcntl_fork(); if ($pid == -1) { exit(pcntl_get_last_error() . ': ' . pcntl_strerror(pcntl_get_last_error())); } elseif ($pid == 0) { exit(); } sleep(60); exit("Done"); This also creates a <defunct> process when pcntl_signal(SIGCHLD, SIG_IGN) should have removed it. ------------------------------------------------------------------------ [2016-12-19 10:25:14] zorg at razza dot org Description: ------------ The use of pcntl_signal(SIGCHLD, SIG_IGN) breaks sleep(). In 7.0 the below script would sleep for 60 seconds then exit, in 7.1 the script does not sleep at all. Test script: --------------- pcntl_signal(SIGCHLD, SIG_IGN); sleep(60); exit('Done'); Expected result: ---------------- Sleep for 60 seconds, print 'Done' and exit. Actual result: -------------- Instantly prints 'Done' and exist. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=73783&edit=1

« previous php.bugs (#206160) next »