php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #17538 proc_close() doesn't return exit value of process
Submitted: 2002-05-30 21:19 UTC Modified: 2002-08-02 10:41 UTC
Votes:3
Avg. Score:5.0 ± 0.0
Reproduced:3 of 3 (100.0%)
Same Version:3 (100.0%)
Same OS:3 (100.0%)
From: kims at contrail dot com dot au Assigned: jflemer (profile)
Status: Closed Package: Filesystem function related
PHP Version: 4.0CVS-2002-05-30 OS: Debian GNU/Linux
Private report: No CVE-ID: None
 [2002-05-30 21:19 UTC] kims at contrail dot com dot au
proc_close() seems to always return -1, instead of the exit value of the process it closed. I feel that this a bug in proc_close().

If proc_close() is returning -1 because of some sort of error or problem, then the online manual (http://www.php.net/proc_close) needs to specify what conditions make proc_close return -1.

Here's a script that reproduces the problem.

Thanks :)

<?
	/* costants to use with the $pipes array */
	define(BASH_STDIN, 0);
	define(BASH_STDOUT, 1);
	
	/* a random exit code, just to keep things interesting */
	$bashexit = rand(100, 199);

/* a shell script to write to bash's STDIN */
	$shellscript .=
"
echo I am bash, and I will return an exit code of $bashexit
exit $bashexit
";

	/* run bash, with pipes to/from stdin and stdout */
	$bash = proc_open(
		"bash",
		array(
			0 => array("pipe", "r"),
			1 => array("pipe", "w"),
			2 => array("file", "/tmp/bashstderr", "a")
		),
		$pipes
	);

	/* write the prepared shell script to bash's STDIN */
	fwrite($pipes[BASH_STDIN], $shellscript);
	
	/* close pipe to bash's STDIN */
	fclose($pipes[BASH_STDIN]);

	echo "bash's stdout:\n";

	/* read and echo output from bash, one byte at a time */
	while(!feof($pipes[BASH_STDOUT]))
		echo fread($pipes[BASH_STDOUT], 1);

	/* close pipe from bash's STDOUT */
	fclose($pipes[BASH_STDOUT]);
	
	echo "\n";

	$realexit = proc_close($bash);
	echo "bash's exit code: $realexit\n\n";
	
	if ($realexit != $bashexit)
		echo "process exit code was $bashexit proc_close() returned $realexit!\n";
?>

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2002-05-31 00:16 UTC] kims at contrail dot com dot au
For what it's worth, this problem also occurrs when php is compiled with --enable-sigchild.
 [2002-08-01 11:35 UTC] jflemer@php.net
Also w/ 4.3 SNAP 2002-07-03-1200 on RedHat 7.3.
Config ops: --with-apxs --with-mysql=/usr/local/mysql --with-dom --with-xmlrpc --with-zlib-dir=/usr

Always seems to return -1.
 [2002-08-01 11:48 UTC] jflemer@php.net
Do you think this could do it?

Index: ext/standard/exec.c
===================================================================
RCS file: /repository/php4/ext/standard/exec.c,v
retrieving revision 1.77
diff -u -r1.77 exec.c
--- ext/standard/exec.c	8 Jul 2002 12:52:22 -0000	1.77
+++ ext/standard/exec.c	1 Aug 2002 15:47:29 -0000
@@ -567,7 +567,7 @@
 
 	do {
 		wait_pid = waitpid(child, &wstatus, 0);
-	} while (wait_pid == -1 && errno = EINTR);
+	} while (wait_pid == -1 && errno == EINTR);
 	
 	if (wait_pid == -1)
 		FG(pclose_ret) = -1;

 [2002-08-01 12:09 UTC] jflemer@php.net
By the way, it also seems to make lots of zombies, which is probably related.
 [2002-08-01 15:49 UTC] jflemer@php.net
Patch applied by rasmus. Please try latest CVS (or snapshot after now).
 [2002-08-01 16:26 UTC] kalowsky@php.net
marking as feedback until user tests new snapshot.
 [2002-08-01 17:44 UTC] kims at contrail dot com dot au
With the renewed interest in this bug, here's a patch I posted to php-dev some time ago. You need the other code in this patch so as to actually return the *correct* exit value, which I don't think the other patch will neccesarily do (although it won't return -1).

? proc_close_patch
Index: ext/standard/exec.c
===================================================================
RCS file: /repository/php4/ext/standard/exec.c,v
retrieving revision 1.76
diff -u -r1.76 exec.c
--- ext/standard/exec.c	23 May 2002 10:17:07 -0000	1.76
+++ ext/standard/exec.c	13 Jun 2002 00:03:21 -0000
@@ -559,23 +559,33 @@
 	GetExitCodeProcess(child, &wstatus);
 	FG(pclose_ret) = wstatus;
 #else
-# if HAVE_SYS_WAIT
+#if HAVE_SYS_WAIT_H
 	int wstatus;
 	pid_t child, wait_pid;
 	
 	child = (pid_t)rsrc->ptr;
 
 	do {
+		/* fetch status of child process */
 		wait_pid = waitpid(child, &wstatus, 0);
-	} while (wait_pid == -1 && errno = EINTR);
+		
+		/* if wait_pid == 1 and errno == EINTR, then waitpid() is just
+		 * alerting of a signal that's been caught - so keep looping
+		 * until wait_pid != -1 (the child process has exited) or
+		 * errno != EINTR (there was a real error, not just a caught
+		 * signal)
+		 */
+	} while (wait_pid == -1 && errno == EINTR);
 	
-	if (wait_pid == -1)
-		FG(pclose_ret) = -1;
-	else
-		FG(pclose_ret) = wstatus;
-# else
+	/* if the child process exited normally, set pclose_ret to the exit
+	 * status of the child process, otherwise set it to -1 (this might
+	 * happen if there's no child process, or it didn't exit normally)
+	 */
+	FG(pclose_ret) = wait_pid > 0 && WIFEXITED(wstatus) ? 
+		WEXITSTATUS(wstatus) : -1;
+#else
 	FG(pclose_ret) = -1;
-# endif
+#endif
 #endif
 }
 [2002-08-02 10:41 UTC] jflemer@php.net
Fixed in CVS.

Fixed typo in #if, thanks kims@contrail.com.au. I didn't apply the rest of her patch though, becuase that should be left to the script (like in pclose()), by saying:  $ret = (proc_close($proc) >> 8) & 0xff;

Tested on FreeBSD 4.6-stable. No more zombies and correct exit code.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 22:01:28 2024 UTC