Bug #66437 [Com]: proc_close misbehaves if proc_get_status was used
| From: | phpbugs2012 at joern dot heissler dot de | Date: | Wed, 08 Jan 2014 00:22:56 +0000 |
| Subject: | Bug #66437 [Com]: proc_close misbehaves if proc_get_status was used | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-183636@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=66437&edit=1
ID: 66437
Comment by: phpbugs2012 at joern dot heissler dot de
Reported by: phpbugs2012 at joern dot heissler dot de
Summary: proc_close misbehaves if proc_get_status was used
Status: Feedback
Type: Bug
Package: Program Execution
Operating System: Linux
PHP Version: 5.5.7
Block user comment: N
Private report: N
New Comment:
Thanks for the really quick patch!
ext/standard/file.c can't be compiled, popen seems to use the same global vars.
Same for main/streams/streams.c
I commented out the noncompiling code so that I can test the proc_⦠functions.
I still see wait4 (i.e. waitpid) in the strace for proc_get_status after the child terminated.
Previous Comments:
------------------------------------------------------------------------
[2014-01-07 20:19:28] krakjoe@php.net
Please test attached patch.
------------------------------------------------------------------------
[2014-01-07 20:18:49] krakjoe@php.net
The following patch has been added/updated:
Patch Name: proc-open-stuff.patch
Revision: 1389125929
URL: https://bugs.php.net/patch-display.php?bug=66437&patch=proc-open-stuff.patch&revision=1389125929
------------------------------------------------------------------------
[2014-01-07 17:50:12] phpbugs2012 at joern dot heissler dot de
Description:
------------
I have several sub processes (created with proc_open) which terminate in unspecified order. To know
which processes terminate, I check each with proc_get_status. When `running' is false, I call
proc_close to free the resources.
proc_close always returns -1 instead of the real exit status. Seems to be an old bug
(http://de2.php.net/manual/en/function.proc-close.php#83622), but I couldn't find a bug report
yet.
I'm not too familiar with php's source code, but this is what I think happens:
proc_get_status calls waitpid, reaping the child zombie process.
proc_close diminishes the reference counter on the process handle which causes the destructor
(proc_open_rsrc_dtor) to do its job. HAVE_SYS_WAIT_H should be defined on my system, so once again
waitpid is called. On a process which doesn't exist anymore. waitpid returns -1 with errno ==
ECHILD. The status -1 is stored in a global variable file_globals.pclose_ret and returned by
proc_close.
The code should be rewritten. At least two things can go wrong:
* proc_close can return a wrong status (-1) when proc_get_status or another wait/waitpid function
was called
* If a new process with the same process id came into existence between proc_get_status and
proc_close, proc_close may hang.
Suggested fix:
proc_close and proc_get_status should call a common function which calls waitpid (with or without
WNOHANG etc.). The returned status is stored in the resource object, not globally. When waitpid
succeeded before, it must not be called again, the status can be taken from the saved data instead.
Test script:
---------------
<?php
$p = proc_open('sleep 1', array(), $foo);
do {
usleep(100000);
$s = proc_get_status($p);
echo $s['running'] ? 'Running' : 'Finished', PHP_EOL;
} while ($s['running']);
$q = proc_open('sleep 3600', array(), $foo);
echo proc_close($p), PHP_EOL;
Expected result:
----------------
Running
Running
Running
...
Finished
0
Actual result:
--------------
Running
Running
Running
...
Finished
-1
or, if you're unlucky, the proc_close will hang for an hour if $q has the same process ID that
$p had before.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=66437&edit=1