Skip to content
This repository has been archived by the owner on Dec 16, 2019. It is now read-only.

Commit

Permalink
Copy stdin, stdout and stderr at thread creation (#831)
Browse files Browse the repository at this point in the history
* Copy stdin, stdout and stderr at thread creation

* Duplicate the handles, reimport via streams API

* php73 support
  • Loading branch information
sirsnyder authored Jan 26, 2019
1 parent 7de8ffd commit 8f4205d
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 3 deletions.
59 changes: 58 additions & 1 deletion src/prepare.c
Original file line number Diff line number Diff line change
Expand Up @@ -590,10 +590,65 @@ static inline void pthreads_prepare_ini(pthreads_object_t* thread) {
} /* }}} */

/* {{{ */
static inline void pthreads_prepare_constants(pthreads_object_t* thread) {
static inline void pthreads_prepare_stdio_constants(pthreads_object_t* thread) {
zend_constant *zconstant;
zend_string *name;
int stdio_in, stdio_out, stdio_err;

ZEND_HASH_FOREACH_STR_KEY_PTR(PTHREADS_EG(thread->creator.ls, zend_constants), name, zconstant) {
int fd = -1;
php_stream * stream = NULL;
const char *mode = NULL;

if (zconstant->name) {
stdio_in = strncmp(name->val, "STDIN", name->len-1)==0;
stdio_out = strncmp(name->val, "STDOUT", name->len-1)==0;
stdio_err = strncmp(name->val, "STDERR", name->len-1)==0;

if((stdio_in || stdio_out || stdio_err) && !pthreads_constant_exists(name)) {
zend_constant constant;

if(stdio_in) {
fd = dup(STDIN_FILENO);
mode = "rb";
} else if(stdio_out) {
fd = dup(STDOUT_FILENO);
mode = "wb";
} else if(stdio_err) {
fd = dup(STDERR_FILENO);
mode = "wb";
}

if (fd == -1) {
continue;
}
stream = php_stream_fopen_from_fd(fd, mode, NULL);

if (stream == NULL) {
close(fd);
continue;
}
php_stream_to_zval(stream, &constant.value);

#if PHP_VERSION_ID < 70300
constant.flags = zconstant->flags;
constant.module_number = zconstant->module_number;
#else
ZEND_CONSTANT_SET_FLAGS(&constant, ZEND_CONSTANT_FLAGS(zconstant), ZEND_CONSTANT_MODULE_NUMBER(zconstant));
#endif
constant.name = zend_string_new(name);

zend_register_constant(&constant);
}
}
} ZEND_HASH_FOREACH_END();
} /* }}} */

/* {{{ */
static inline void pthreads_prepare_constants(pthreads_object_t* thread) {
zend_constant *zconstant;
zend_string *name;

ZEND_HASH_FOREACH_STR_KEY_PTR(PTHREADS_EG(thread->creator.ls, zend_constants), name, zconstant) {
if (zconstant->name) {
if (strncmp(name->val, "STDIN", name->len-1)==0||
Expand Down Expand Up @@ -761,6 +816,8 @@ int pthreads_prepared_startup(pthreads_object_t* thread, pthreads_monitor_t *rea
if (thread->options & PTHREADS_INHERIT_INI)
pthreads_prepare_ini(thread);

pthreads_prepare_stdio_constants(thread);

if (thread->options & PTHREADS_INHERIT_CONSTANTS)
pthreads_prepare_constants(thread);

Expand Down
4 changes: 2 additions & 2 deletions tests/complex-statics-set-null.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,10 @@ array(1) {
file::_get: something3
array(1) {
[%i]=>
resource(2) of type (stream)
resource(5) of type (stream)
}
file::_get: something4
array(1) {
[%i]=>
resource(2) of type (stream)
resource(5) of type (stream)
}
22 changes: 22 additions & 0 deletions tests/constant-stdio-copy-inherit-all.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
Testing stdio constants STDIN / STDOUT / STDERR #806 and #583
--DESCRIPTION--
Copy stdin, stdout and stderr at thread creation with PTHREADS_INHERIT_ALL.
--FILE--
<?php
$thread = new class extends \Thread{
public function run(){
var_dump(defined('STDOUT'));

fwrite(STDOUT, 'Hello'. PHP_EOL);
}
};

$thread->start(PTHREADS_INHERIT_ALL) && $thread->join();

fwrite(STDOUT, 'World'. PHP_EOL);
?>
--EXPECTF--
bool(true)
Hello
World
22 changes: 22 additions & 0 deletions tests/constant-stdio-copy-inherit-none.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
Testing stdio constants STDIN / STDOUT / STDERR #806 and #583
--DESCRIPTION--
Copy stdin, stdout and stderr at thread creation with PTHREADS_INHERIT_NONE.
--FILE--
<?php
$thread = new class extends \Thread{
public function run(){
var_dump(defined('STDOUT'));

fwrite(STDOUT, 'Hello'. PHP_EOL);
}
};

$thread->start(PTHREADS_INHERIT_NONE) && $thread->join();

fwrite(STDOUT, 'World'. PHP_EOL);
?>
--EXPECTF--
bool(true)
Hello
World

0 comments on commit 8f4205d

Please sign in to comment.