Bug #66437 [Opn->Fbk]: proc_close misbehaves if proc_get_status was used

From: Date: Tue, 07 Jan 2014 20:19:28 +0000
Subject: Bug #66437 [Opn->Fbk]: proc_close misbehaves if proc_get_status was used
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-183635@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 Updated by: krakjoe@php.net Reported by: phpbugs2012 at joern dot heissler dot de Summary: proc_close misbehaves if proc_get_status was used -Status: Open +Status: Feedback Type: Bug Package: Program Execution Operating System: Linux PHP Version: 5.5.7 Block user comment: N Private report: N New Comment: Please test attached patch. Previous Comments: ------------------------------------------------------------------------ [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

« previous php.bugs (#183635) next »