ID:               34794
 Comment by:       jdolecek at NetBSD dot org
 Reported By:      e-t172 at e-t172 dot net
 Status:           Assigned
 Bug Type:         Program Execution
 Operating System: Linux
 PHP Version:      5CVS-2005-10-09 (snap)
 Assigned To:      wez
 New Comment:

Actually yes, there is a severe pipe setup problem.

The problem is that the second spawned process inherits the descriptor
of parent end of pipe to the first spawned process, created when
setting up the process1 pipes. Since PHP doesn't set the close-on-exec
flag, the descriptor stays open in process2.

So, when the parent-end of pipes1[0] is closed in master script, the
descriptor is still open by process2, thus the pipe write end is not
closed yet and thus cat in process1 doesn't end.

Note this is also potential security problem, since the second process
is able to send data to the first.

Fix:

--- ext/standard/proc_open.c.orig   2006-05-28 19:10:35.000000000
+0200
+++ ext/standard/proc_open.c
@@ -929,6 +929,16 @@ PHP_FUNCTION(proc_open)
                            descriptors[i].mode_flags), mode_string,
NULL);
 #else
                stream =
php_stream_fopen_from_fd(descriptors[i].parentend, mode_string, NULL);
+
+#if defined(F_SETFD) && defined(FD_CLOEXEC)
+               /*
+                * Mark the descriptor close-on-exec, so that it
+                * it won't be inherited by potential other children.
+                * This avoids first child deadlock on proc_close().
+                */
+               fcntl(descriptors[i].parentend, F_SETFD, FD_CLOEXEC);
+#endif
+
 #endif
                if (stream) {
                    zval *retfp;


Previous Comments:
------------------------------------------------------------------------

[2006-05-28 17:32:37] jdolecek at NetBSD dot org

This is actually not a bug, or just documentation bug.

proc_close() blocks if the child has not terminated yet. 

You must use proc_terminate() instead of proc_close() if you can't
guarantee the child has already exited, or use proc_get_status() to
check if the child has already exited if you want to avoid blocking.

------------------------------------------------------------------------

[2006-04-29 02:42:16] Dallas at ekkySoftware dot com

I have a similar problem, it seems at I can't concurrently call the
same page with proc_open until the first proc_open returns. It looks
like proc_open is running through a critical section even though it is
opening separate processes.

>From experience it is like php is using the same pipes for each
proc_open and can't continue to the next proc_open until the original
as ended. I would normally use temporary files instead of pipes – but
this makes life difficult.

Dallas

http://www.ekkySoftware.com/

------------------------------------------------------------------------

[2006-04-26 14:50:23] radu dot rendec at ines dot ro

Same problem with 5.1.3RC4-dev (latest CVS snapshot at the moment) on
Linux/i386.

I independently reproduced the bug with the following piece of code:

error_reporting(E_ALL);
$spec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")
        );
$p1 = proc_open("/bin/cat", $spec, $fd1);
$p2 = proc_open("/bin/cat", $spec, $fd2);

fclose($fd1[0]);
fclose($fd1[1]);
fclose($fd1[2]);
echo "closing p1... "; flush();
proc_close($p1);
echo "success\n"; flush();

This code hangs in proc_close(). This doesn't happen if the second
proc_open() is commented.

Although the parent process seems to correctly close all pipes, the
child process still remains blocked in read(0,...).

------------------------------------------------------------------------

[2005-11-01 11:54:27] [EMAIL PROTECTED]

Assigned to the author of this stuff.

------------------------------------------------------------------------

[2005-10-09 20:12:09] e-t172 at e-t172 dot net

Same problem with the last CVS Snapshot.

------------------------------------------------------------------------

The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
    http://bugs.php.net/34794

-- 
Edit this bug report at http://bugs.php.net/?id=34794&edit=1

Reply via email to