Skip to content

Commit 4c5682b

Browse files
committed
fix(pty): fix pty being on the same fd
1 parent 94f3272 commit 4c5682b

File tree

2 files changed

+26
-40
lines changed

2 files changed

+26
-40
lines changed

ext/standard/proc_open.c

+25-39
Original file line numberDiff line numberDiff line change
@@ -845,32 +845,6 @@ static zend_result set_proc_descriptor_to_blackhole(descriptorspec_item *desc)
845845
return SUCCESS;
846846
}
847847

848-
static zend_result set_proc_descriptor_to_pty(descriptorspec_item *desc, int *master_fd, int *slave_fd)
849-
{
850-
#ifdef HAVE_OPENPTY
851-
/* All FDs set to PTY in the child process will go to the slave end of the same PTY.
852-
* Likewise, all the corresponding entries in `$pipes` in the parent will all go to the master
853-
* end of the same PTY.
854-
* If this is the first descriptorspec set to 'pty', find an available PTY and get master and
855-
* slave FDs. */
856-
if (*master_fd == -1) {
857-
if (openpty(master_fd, slave_fd, NULL, NULL, NULL)) {
858-
php_error_docref(NULL, E_WARNING, "Could not open PTY (pseudoterminal): %s", strerror(errno));
859-
return FAILURE;
860-
}
861-
}
862-
863-
desc->type = DESCRIPTOR_TYPE_PIPE;
864-
desc->childend = dup(*slave_fd);
865-
desc->parentend = dup(*master_fd);
866-
desc->mode_flags = O_RDWR;
867-
return SUCCESS;
868-
#else
869-
php_error_docref(NULL, E_WARNING, "PTY (pseudoterminal) not supported on this system");
870-
return FAILURE;
871-
#endif
872-
}
873-
874848
/* Mark the descriptor close-on-exec, so it won't be inherited by children */
875849
static php_file_descriptor_t make_descriptor_cloexec(php_file_descriptor_t fd)
876850
{
@@ -884,6 +858,28 @@ static php_file_descriptor_t make_descriptor_cloexec(php_file_descriptor_t fd)
884858
#endif
885859
}
886860

861+
static zend_result set_proc_descriptor_to_pty(descriptorspec_item *desc)
862+
{
863+
#ifdef HAVE_OPENPTY
864+
int master_fd = -1, slave_fd = -1;
865+
866+
/* Find an available PTY and get master and slave FDs. */
867+
if (openpty(&master_fd, &slave_fd, NULL, NULL, NULL)) {
868+
php_error_docref(NULL, E_WARNING, "Could not open PTY (pseudoterminal): %s", strerror(errno));
869+
return FAILURE;
870+
}
871+
872+
desc->type = DESCRIPTOR_TYPE_PIPE;
873+
desc->childend = make_descriptor_cloexec(slave_fd);
874+
desc->parentend = make_descriptor_cloexec(master_fd);
875+
desc->mode_flags = O_RDWR;
876+
return SUCCESS;
877+
#else
878+
php_error_docref(NULL, E_WARNING, "PTY (pseudoterminal) not supported on this system");
879+
return FAILURE;
880+
#endif
881+
}
882+
887883
static zend_result set_proc_descriptor_to_pipe(descriptorspec_item *desc, zend_string *zmode)
888884
{
889885
php_file_descriptor_t newpipe[2];
@@ -1031,7 +1027,7 @@ static zend_result redirect_proc_descriptor(descriptorspec_item *desc, int targe
10311027

10321028
/* Process one item from `$descriptorspec` argument to `proc_open` */
10331029
static zend_result set_proc_descriptor_from_array(zval *descitem, descriptorspec_item *descriptors,
1034-
int ndesc, int nindex, int *pty_master_fd, int *pty_slave_fd) {
1030+
int ndesc, int nindex) {
10351031
zend_string *ztype = get_string_parameter(descitem, 0, "handle qualifier");
10361032
if (!ztype) {
10371033
return FAILURE;
@@ -1078,7 +1074,7 @@ static zend_result set_proc_descriptor_from_array(zval *descitem, descriptorspec
10781074
retval = set_proc_descriptor_to_blackhole(&descriptors[ndesc]);
10791075
} else if (zend_string_equals_literal(ztype, "pty")) {
10801076
/* Set descriptor to slave end of PTY */
1081-
retval = set_proc_descriptor_to_pty(&descriptors[ndesc], pty_master_fd, pty_slave_fd);
1077+
retval = set_proc_descriptor_to_pty(&descriptors[ndesc]);
10821078
} else {
10831079
php_error_docref(NULL, E_WARNING, "%s is not a valid descriptor spec/mode", ZSTR_VAL(ztype));
10841080
goto finish;
@@ -1229,7 +1225,6 @@ PHP_FUNCTION(proc_open)
12291225
#else
12301226
char **argv = NULL;
12311227
#endif
1232-
int pty_master_fd = -1, pty_slave_fd = -1;
12331228
php_process_id_t child;
12341229
php_process_handle *proc;
12351230

@@ -1302,8 +1297,7 @@ PHP_FUNCTION(proc_open)
13021297
goto exit_fail;
13031298
}
13041299
} else if (Z_TYPE_P(descitem) == IS_ARRAY) {
1305-
if (set_proc_descriptor_from_array(descitem, descriptors, ndesc, (int)nindex,
1306-
&pty_master_fd, &pty_slave_fd) == FAILURE) {
1300+
if (set_proc_descriptor_from_array(descitem, descriptors, ndesc, (int)nindex) == FAILURE) {
13071301
goto exit_fail;
13081302
}
13091303
} else {
@@ -1554,14 +1548,6 @@ PHP_FUNCTION(proc_open)
15541548
free(envpw);
15551549
#else
15561550
efree_argv(argv);
1557-
#endif
1558-
#ifdef HAVE_OPENPTY
1559-
if (pty_master_fd != -1) {
1560-
close(pty_master_fd);
1561-
}
1562-
if (pty_slave_fd != -1) {
1563-
close(pty_slave_fd);
1564-
}
15651551
#endif
15661552
if (descriptors) {
15671553
efree(descriptors);

ext/standard/tests/file/bug69442.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ function read_from_pipe($pipe) {
4141
return $result;
4242
}
4343

44-
$data0 = read_from_pipe($pipes[0]);
44+
$data0 = read_from_pipe($pipes[1]);
4545
echo 'read from pipe 0: ';
4646
var_dump($data0);
4747
fclose($pipes[0]);

0 commit comments

Comments
 (0)