diff --git a/ext/posix/php_posix.h b/ext/posix/php_posix.h index ebd449231dda8..50dff8203cef2 100644 --- a/ext/posix/php_posix.h +++ b/ext/posix/php_posix.h @@ -114,6 +114,7 @@ PHP_FUNCTION(posix_getrlimit); PHP_FUNCTION(posix_initgroups); #endif +void php_posix_set_last_error(int TSRMLS_DC); PHP_FUNCTION(posix_get_last_error); PHP_FUNCTION(posix_strerror); diff --git a/ext/posix/posix.c b/ext/posix/posix.c index ca7d34c645a03..62bbe09840ffb 100644 --- a/ext/posix/posix.c +++ b/ext/posix/posix.c @@ -1322,6 +1322,12 @@ PHP_FUNCTION(posix_getrlimit) #endif /* HAVE_GETRLIMIT */ +void php_posix_set_last_error(int error TSRMLS_DC) /* {{{ */ +{ + POSIX_G(last_error) = error; +} +/* }}} */ + /* {{{ proto int posix_get_last_error(void) Retrieve the error number set by the last posix function which failed. */ PHP_FUNCTION(posix_get_last_error) diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 51e3c14e7af3e..13026f03a2c84 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -31,6 +31,10 @@ #include "php_network.h" #include "php_string.h" +#if HAVE_POSIX +#include "ext/posix/php_posix.h" +#endif + #ifndef PHP_WIN32 #define php_select(m, r, w, e, t) select(m, r, w, e, t) typedef unsigned long long php_timeout_ull; @@ -62,6 +66,8 @@ PHP_FUNCTION(stream_socket_pair) if (0 != socketpair((int)domain, (int)type, (int)protocol, pair)) { char errbuf[256]; + if (zend_hash_str_exists(&module_registry, "posix", sizeof("posix")-1)) + php_posix_set_last_error(php_socket_errno() TSRMLS_CC); php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create sockets: [%d]: %s", php_socket_errno(), php_socket_strerror(php_socket_errno(), errbuf, sizeof(errbuf))); RETURN_FALSE; @@ -809,6 +815,8 @@ PHP_FUNCTION(stream_select) retval = php_select(max_fd+1, &rfds, &wfds, &efds, tv_p); if (retval == -1) { + if (zend_hash_str_exists(&module_registry, "posix", sizeof("posix")-1)) + php_posix_set_last_error(errno TSRMLS_CC); php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s (max_fd=%d)", errno, strerror(errno), max_fd); RETURN_FALSE; diff --git a/ext/standard/tests/streams/bug34380_01.phpt b/ext/standard/tests/streams/bug34380_01.phpt new file mode 100644 index 0000000000000..769fcfe1cb635 --- /dev/null +++ b/ext/standard/tests/streams/bug34380_01.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #34380: stream_socket_pair should set posix_globals.last_error on failure +--SKIPIF-- + +--FILE-- + +--EXPECTF-- + +Warning: stream_socket_pair(): failed to create sockets: [95]: Operation not supported in %s on line %d +bool(false) +int(95) diff --git a/ext/standard/tests/streams/bug34380_02.phpt b/ext/standard/tests/streams/bug34380_02.phpt new file mode 100644 index 0000000000000..b215b05fcc4fc --- /dev/null +++ b/ext/standard/tests/streams/bug34380_02.phpt @@ -0,0 +1,44 @@ +--TEST-- +Bug #34380: stream_select should set posix_globals.last_error on failure +--SKIPIF-- + +--FILE-- + array('pipe', 'r'), + 1 => array('pipe', 'w'), + 2 => array('pipe', 'w') + ); + $proc = proc_open('/bin/sleep 60', $open_spec, $pipes, NULL, $_ENV); + $reads = array($pipes[1]); + $e = NULL; + + // should get EINTR after child sends us a signal + $fds = stream_select($reads, $e, $e, 60); + var_dump($fds); + var_dump(posix_get_last_error()); + proc_terminate($proc); +} else { + // racy + sleep(2); + posix_kill(posix_getppid(), SIGUSR2); +} +?> +--EXPECTF-- + +Warning: stream_select(): unable to select [4]: Interrupted system call (max_fd=%d) in %s on line %d +bool(false) +int(4)