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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: kims at contrail dot com dot au
New email:
PHP Version: OS:

 

 [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: Fri Nov 22 04:01:28 2024 UTC