Skip to content

Dereferencing process-handles no longer waits on those processes #130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 201?, PHP 5.6.0

- General improvements:
. Implemented FR #46487 (Dereferencing process-handles no longer waits on those processes). (Jille Timmermans)

<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
3 changes: 3 additions & 0 deletions ext/standard/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ static ZEND_RSRC_DTOR_FUNC(file_context_dtor)
static void file_globals_ctor(php_file_globals *file_globals_p TSRMLS_DC)
{
FG(pclose_ret) = 0;
FG(pclose_wait) = 0;
FG(user_stream_current_filename) = NULL;
FG(def_chunk_size) = PHP_SOCK_CHUNK_SIZE;
FG(wrapper_errors) = NULL;
Expand Down Expand Up @@ -960,7 +961,9 @@ PHP_FUNCTION(pclose)

PHP_STREAM_TO_ZVAL(stream, &arg1);

FG(pclose_wait) = 1;
zend_list_delete(stream->rsrc_id);
FG(pclose_wait) = 0;
RETURN_LONG(FG(pclose_ret));
}
/* }}} */
Expand Down
3 changes: 2 additions & 1 deletion ext/standard/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ typedef struct _php_meta_tags_data {
php_meta_tags_token php_next_meta_token(php_meta_tags_data * TSRMLS_DC);

typedef struct {
int pclose_ret;
int pclose_ret;
size_t def_chunk_size;
long auto_detect_line_endings;
long default_socket_timeout;
Expand All @@ -126,6 +126,7 @@ typedef struct {
HashTable *stream_wrappers; /* per-request copy of url_stream_wrappers_hash */
HashTable *stream_filters; /* per-request copy of stream_filters_hash */
HashTable *wrapper_errors; /* key: wrapper address; value: linked list of char* */
int pclose_wait;
} php_file_globals;

#ifdef ZTS
Expand Down
20 changes: 16 additions & 4 deletions ext/standard/proc_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
DWORD wstatus;
#elif HAVE_SYS_WAIT_H
int wstatus;
int waitpid_options = 0;
pid_t wait_pid;
#endif

Expand All @@ -220,18 +221,27 @@ static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
}

#ifdef PHP_WIN32
WaitForSingleObject(proc->childHandle, INFINITE);
if (FG(pclose_wait)) {
WaitForSingleObject(proc->childHandle, INFINITE);
}
GetExitCodeProcess(proc->childHandle, &wstatus);
FG(pclose_ret) = wstatus;
if (wstatus == STILL_ACTIVE) {
FG(pclose_ret) = -1;
} else {
FG(pclose_ret) = wstatus;
}
CloseHandle(proc->childHandle);

#elif HAVE_SYS_WAIT_H

if (!FG(pclose_wait)) {
waitpid_options = WNOHANG;
}
do {
wait_pid = waitpid(proc->child, &wstatus, 0);
wait_pid = waitpid(proc->child, &wstatus, waitpid_options);
} while (wait_pid == -1 && errno == EINTR);

if (wait_pid == -1) {
if (wait_pid <= 0) {
FG(pclose_ret) = -1;
} else {
if (WIFEXITED(wstatus))
Expand Down Expand Up @@ -300,7 +310,9 @@ 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));
}
/* }}} */
Expand Down
35 changes: 35 additions & 0 deletions ext/standard/tests/general_functions/implicit_proc_close.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
--TEST--
Implicit proc_close()s (by the GC) should not wait for the process to exit.
--SKIPIF--
<?php
if(!is_executable("/bin/sleep")) {
echo "skip";
}
if(!function_exists("proc_open")) {
echo "skip proc_open() is not available";
}
?>
--FILE--
<?php
$descr = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);

$ph = proc_open(
"/bin/sleep 2",
$descr,
$pipes
);
$t = microtime(true);
unset($ph);
$t = microtime(true) - $t;
if($t < 1) {
echo "Fast enough.\n";
} else {
var_dump($t);
}
?>
--EXPECT--
Fast enough.