php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #66437
Patch proc-open-stuff.patch revision 2014-01-08 07:15 UTC by krakjoe@php.net
revision 2014-01-07 20:18 UTC by krakjoe@php.net

Patch proc-open-stuff.patch for Program Execution Bug #66437

Patch version 2014-01-08 07:15 UTC

Return to Bug #66437 | Download this patch
This patch renders other patches obsolete

Obsolete patches:

Patch Revisions:

Developer: krakjoe@php.net

diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index 1e37e64..5c9056d 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -199,10 +199,7 @@ static void _php_free_envp(php_process_env_t env, int is_persistent)
 }
 /* }}} */
 
-/* {{{ proc_open_rsrc_dtor */
-static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
-{
-	struct php_process_handle *proc = (struct php_process_handle*)rsrc->ptr;
+static void proc_close_func(struct php_process_handle *proc TSRMLS_DC) { /* {{{ */
 	int i;
 #ifdef PHP_WIN32
 	DWORD wstatus;
@@ -219,39 +216,56 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
 			proc->pipes[i] = 0;
 		}
 	}
+	
+	if (proc->closed) {
+		return;
+	}
 
 #ifdef PHP_WIN32
-	if (FG(pclose_wait)) {
+	if (proc->wait) {
 		WaitForSingleObject(proc->childHandle, INFINITE);
 	}
 	GetExitCodeProcess(proc->childHandle, &wstatus);
 	if (wstatus == STILL_ACTIVE) {
-		FG(pclose_ret) = -1;
+		proc->ret = -1;
 	} else {
-		FG(pclose_ret) = wstatus;
+		proc->ret = wstatus;
 	}
 	CloseHandle(proc->childHandle);
 
 #elif HAVE_SYS_WAIT_H
 
-	if (!FG(pclose_wait)) {
+	if (!proc->wait) {
 		waitpid_options = WNOHANG;
 	}
+	
 	do {
 		wait_pid = waitpid(proc->child, &wstatus, waitpid_options);
 	} while (wait_pid == -1 && errno == EINTR);
 
 	if (wait_pid <= 0) {
-		FG(pclose_ret) = -1;
+		proc->ret = -1;
 	} else {
 		if (WIFEXITED(wstatus))
-			wstatus = WEXITSTATUS(wstatus);
-		FG(pclose_ret) = wstatus;
+			proc->ret = WEXITSTATUS(wstatus);
 	}
 
 #else
-	FG(pclose_ret) = -1;
+	proc->ret = -1
 #endif
+
+	proc->closed = 1;
+} /* }}} */
+
+/* {{{ proc_open_rsrc_dtor */
+static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+	struct php_process_handle *proc = (struct php_process_handle*)rsrc->ptr;
+	
+	if (!proc->closed) {
+		proc_close_func(proc TSRMLS_CC);
+	}
+	
 	_php_free_envp(proc->env, proc->is_persistent);
 	pefree(proc->command, proc->is_persistent);
 	pefree(proc, proc->is_persistent);
@@ -281,6 +295,10 @@ PHP_FUNCTION(proc_terminate)
 
 	ZEND_FETCH_RESOURCE(proc, struct php_process_handle *, &zproc, -1, "process", le_proc_open);
 
+	if (proc->closed) {
+		RETURN_TRUE;
+	}
+
 #ifdef PHP_WIN32
 	if (TerminateProcess(proc->childHandle, 255)) {
 		RETURN_TRUE;
@@ -310,10 +328,13 @@ PHP_FUNCTION(proc_close)
 
 	ZEND_FETCH_RESOURCE(proc, struct php_process_handle *, &zproc, -1, "process", le_proc_open);
 
-	FG(pclose_wait) = 1;
-	zend_list_delete(Z_LVAL_P(zproc));
-	FG(pclose_wait) = 0;
-	RETURN_LONG(FG(pclose_ret));
+	if (!proc->closed) {
+		proc->wait = 1;
+		proc_close_func(proc TSRMLS_CC);
+		proc->wait = 0;
+	}
+	
+	RETURN_LONG(proc->ret);
 }
 /* }}} */
 
@@ -347,19 +368,23 @@ PHP_FUNCTION(proc_get_status)
 
 	GetExitCodeProcess(proc->childHandle, &wstatus);
 
-	running = wstatus == STILL_ACTIVE;
-	exitcode = running ? -1 : wstatus;
+	if (!(wstatus == STILL_ACTIVE)) {
+		proc->closed = 1;
+	}
+	
+	proc->ret = !proc->closed ? -1 : wstatus;
 
 #elif HAVE_SYS_WAIT_H
 
 	errno = 0;
 	wait_pid = waitpid(proc->child, &wstatus, WNOHANG|WUNTRACED);
 
-	if (wait_pid == proc->child) {
+	if ((wait_pid == proc->child)) {
 		if (WIFEXITED(wstatus)) {
-			running = 0;
-			exitcode = WEXITSTATUS(wstatus);
+			proc->closed = 1;
+			proc->ret = WEXITSTATUS(wstatus);
 		}
+		
 		if (WIFSIGNALED(wstatus)) {
 			running = 0;
 			signaled = 1;
@@ -372,16 +397,17 @@ PHP_FUNCTION(proc_get_status)
 		if (WIFSTOPPED(wstatus)) {
 			stopped = 1;
 			stopsig = WSTOPSIG(wstatus);
+			proc->closed = 1;
 		}
 	} else if (wait_pid == -1) {
-		running = 0;
+		proc->closed = 1;
 	}
 #endif
 
-	add_assoc_bool(return_value, "running", running);
+	add_assoc_bool(return_value, "running", !proc->closed);
 	add_assoc_bool(return_value, "signaled", signaled);
 	add_assoc_bool(return_value, "stopped", stopped);
-	add_assoc_long(return_value, "exitcode", exitcode);
+	add_assoc_long(return_value, "exitcode", proc->ret);
 	add_assoc_long(return_value, "termsig", termsig);
 	add_assoc_long(return_value, "stopsig", stopsig);
 }
@@ -886,6 +912,10 @@ PHP_FUNCTION(proc_open)
 	/* we forked/spawned and this is the parent */
 
 	proc = (struct php_process_handle*)pemalloc(sizeof(struct php_process_handle), is_persistent);
+	proc->closed = 0;
+	proc->ret = -1;
+	proc->wait = 0;
+	
 	proc->is_persistent = is_persistent;
 	proc->command = command;
 	proc->npipes = ndesc;
@@ -963,7 +993,7 @@ PHP_FUNCTION(proc_open)
 				proc->pipes[i] = 0;
 		}
 	}
-
+	
 	ZEND_REGISTER_RESOURCE(return_value, proc, le_proc_open);
 	return;
 
diff --git a/ext/standard/proc_open.h b/ext/standard/proc_open.h
index 6708fde..5e3f621 100644
--- a/ext/standard/proc_open.h
+++ b/ext/standard/proc_open.h
@@ -46,6 +46,9 @@ struct php_process_handle {
 	int npipes;
 	long pipes[PHP_PROC_OPEN_MAX_DESCRIPTORS];
 	char *command;
+	int wait;
+	int ret;
+	int closed;
 	int is_persistent;
 	php_process_env_t env;
 };
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Mar 28 12:01:27 2024 UTC