From 734d907aa4d5f6005c1c32e2d5a229b059954d81 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Tue, 30 Jun 2015 15:47:25 +0200 Subject: [PATCH] initial stuff to make allow blocking pipes on windows --- ext/standard/php_fopen_wrapper.c | 9 +++++++++ ext/standard/proc_open.c | 9 +++++++++ main/streams/plain_wrapper.c | 24 ++++++++++++++++++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/ext/standard/php_fopen_wrapper.c b/ext/standard/php_fopen_wrapper.c index f004c943b5..c3bd4b0048 100644 --- a/ext/standard/php_fopen_wrapper.c +++ b/ext/standard/php_fopen_wrapper.c @@ -400,6 +400,15 @@ php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, const char *pa if (stream == NULL) { close(fd); } +#ifdef PHP_WIN32 + { + zval *blocking_pipes = php_stream_context_get_option(context, "pipe", "blocking"); + if (blocking_pipes) { + convert_to_long(blocking_pipes); + php_stream_set_option(stream, PHP_STREAM_OPTION_PIPE_BLOCKING, Z_LVAL_P(blocking_pipes), NULL); + } + } +#endif } return stream; diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index 27584ea1f2..cee4728a54 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -461,6 +461,7 @@ PHP_FUNCTION(proc_open) #ifdef PHP_WIN32 int suppress_errors = 0; int bypass_shell = 0; + int blocking_pipes = 0; #endif #if PHP_CAN_DO_PTS php_file_descriptor_t dev_ptmx = -1; /* master */ @@ -490,6 +491,13 @@ PHP_FUNCTION(proc_open) bypass_shell = 1; } } + + item = zend_hash_str_find(Z_ARRVAL_P(other_options), "blocking_pipes", sizeof("blocking_pipes") - 1); + if (item != NULL) { + if (Z_TYPE_P(item) == IS_TRUE || ((Z_TYPE_P(item) == IS_LONG) && Z_LVAL_P(item))) { + blocking_pipes = 1; + } + } } #endif @@ -538,6 +546,7 @@ PHP_FUNCTION(proc_open) } #ifdef PHP_WIN32 + php_stream_set_option(stream, PHP_STREAM_OPTION_PIPE_BLOCKING, blocking_pipes, NULL); descriptors[ndesc].childend = dup_fd_as_handle((int)fd); if (descriptors[ndesc].childend == NULL) { php_error_docref(NULL, E_WARNING, "unable to dup File-Handle for descriptor %d", nindex); diff --git a/main/streams/plain_wrapper.c b/main/streams/plain_wrapper.c index e44e1ea348..2fcaa9c645 100644 --- a/main/streams/plain_wrapper.c +++ b/main/streams/plain_wrapper.c @@ -121,7 +121,7 @@ typedef struct { unsigned is_process_pipe:1; /* use pclose instead of fclose */ unsigned is_pipe:1; /* don't try and seek */ unsigned cached_fstat:1; /* sb is valid */ - unsigned _reserved:29; + unsigned is_pipe_blocking; int lock_flag; /* stores the lock state */ zend_string *temp_name; /* if non-null, this is the path to a temporary file that @@ -170,6 +170,9 @@ static php_stream *_php_stream_fopen_from_fd_int(int fd, const char *mode, const self->is_process_pipe = 0; self->temp_name = NULL; self->fd = fd; +#ifndef PHP_WIN32 + is_pipe_blocking = 0; +#endif return php_stream_alloc_rel(&php_stream_stdio_ops, self, persistent_id, mode); } @@ -186,6 +189,9 @@ static php_stream *_php_stream_fopen_from_file_int(FILE *file, const char *mode self->is_process_pipe = 0; self->temp_name = NULL; self->fd = fileno(file); +#ifndef PHP_WIN32 + is_pipe_blocking = 0; +#endif return php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode); } @@ -312,6 +318,9 @@ PHPAPI php_stream *_php_stream_fopen_from_pipe(FILE *file, const char *mode STRE self->is_process_pipe = 1; self->fd = fileno(file); self->temp_name = NULL; +#ifndef PHP_WIN32 + is_pipe_blocking = 0; +#endif stream = php_stream_alloc_rel(&php_stream_stdio_ops, self, 0, mode); stream->flags |= PHP_STREAM_FLAG_NO_SEEK; @@ -356,7 +365,7 @@ static size_t php_stdiop_read(php_stream *stream, char *buf, size_t count) #ifdef PHP_WIN32 php_stdio_stream_data *self = (php_stdio_stream_data*)stream->abstract; - if (self->is_pipe || self->is_process_pipe) { + if ((self->is_pipe || self->is_process_pipe) && !self->is_pipe_blocking) { HANDLE ph = (HANDLE)_get_osfhandle(data->fd); int retry = 0; DWORD avail_read = 0; @@ -832,6 +841,12 @@ static int php_stdiop_set_option(php_stream *stream, int option, int value, void } } +#ifdef PHP_WIN32 + case PHP_STREAM_OPTION_PIPE_BLOCKING: + data->is_pipe_blocking = value; + return PHP_STREAM_OPTION_RETURN_OK; +#endif + default: return PHP_STREAM_OPTION_RETURN_NOTIMPL; } @@ -1005,6 +1020,11 @@ PHPAPI php_stream *_php_stream_fopen(const char *filename, const char *mode, zen return NULL; } } + + if (options & STREAM_USE_BLOCKING_PIPE) { + php_stdio_stream_data *self = (php_stdio_stream_data*)ret->abstract; + self->is_pipe_blocking = 1; + } #endif return ret; -- 2.40.0