Skip to content

Commit 7cafd76

Browse files
Zheaoliashm-devpicnixz
authored
gh-139184: Set O_CLOEXEC for master_fd when calling os.forkpty() (#139408)
Signed-off-by: Manjusaka <[email protected]> Co-authored-by: Shamil <[email protected]> Co-authored-by: Bénédikt Tran <[email protected]>
1 parent f4104f5 commit 7cafd76

File tree

6 files changed

+24
-3
lines changed

6 files changed

+24
-3
lines changed

Doc/library/os.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,6 +4592,8 @@ written in Python, such as a mail server's external command delivery program.
45924592
master end of the pseudo-terminal. For a more portable approach, use the
45934593
:mod:`pty` module. If an error occurs :exc:`OSError` is raised.
45944594

4595+
The returned file descriptor *fd* is :ref:`non-inheritable <fd_inheritance>`.
4596+
45954597
.. audit-event:: os.forkpty "" os.forkpty
45964598

45974599
.. warning::
@@ -4608,6 +4610,9 @@ written in Python, such as a mail server's external command delivery program.
46084610
threads, this now raises a :exc:`DeprecationWarning`. See the
46094611
longer explanation on :func:`os.fork`.
46104612

4613+
.. versionchanged:: next
4614+
The returned file descriptor is now made non-inheritable.
4615+
46114616
.. availability:: Unix, not WASI, not Android, not iOS.
46124617

46134618

Doc/library/pty.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,14 @@ The :mod:`pty` module defines the following functions:
3333
file descriptor connected to the child's controlling terminal (and also to the
3434
child's standard input and output).
3535

36+
The returned file descriptor *fd* is :ref:`non-inheritable <fd_inheritance>`.
37+
3638
.. warning:: On macOS the use of this function is unsafe when mixed with using
3739
higher-level system APIs, and that includes using :mod:`urllib.request`.
3840

41+
.. versionchanged:: next
42+
The returned file descriptor is now made non-inheritable.
43+
3944

4045
.. function:: openpty()
4146

Lib/test/test_pty.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ def test_fork(self):
230230
os._exit(2)
231231
os._exit(4)
232232
else:
233+
self.assertFalse(os.get_inheritable(master_fd))
233234
debug("Waiting for child (%d) to finish." % pid)
234235
# In verbose mode, we have to consume the debug output from the
235236
# child or the child will block, causing this test to hang in the
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:func:`os.forkpty` does now make the returned file descriptor non-inheritable.

Modules/clinic/posixmodule.c.h

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Modules/posixmodule.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9018,11 +9018,12 @@ Returns a tuple of (pid, master_fd).
90189018
Like fork(), return pid of 0 to the child process,
90199019
and pid of child to the parent process.
90209020
To both, return fd of newly opened pseudo-terminal.
9021+
The master_fd is non-inheritable.
90219022
[clinic start generated code]*/
90229023

90239024
static PyObject *
90249025
os_forkpty_impl(PyObject *module)
9025-
/*[clinic end generated code: output=60d0a5c7512e4087 input=f1f7f4bae3966010]*/
9026+
/*[clinic end generated code: output=60d0a5c7512e4087 input=24765e0f33275b3b]*/
90269027
{
90279028
int master_fd = -1;
90289029
pid_t pid;
@@ -9048,13 +9049,20 @@ os_forkpty_impl(PyObject *module)
90489049
} else {
90499050
/* parent: release the import lock. */
90509051
PyOS_AfterFork_Parent();
9052+
/* set O_CLOEXEC on master_fd */
9053+
if (_Py_set_inheritable(master_fd, 0, NULL) < 0) {
9054+
PyErr_FormatUnraisable("Exception ignored when setting master_fd "
9055+
"non-inheritable in forkpty()");
9056+
}
9057+
90519058
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
90529059
if (warn_about_fork_with_threads("forkpty") < 0)
90539060
return NULL;
90549061
}
90559062
if (pid == -1) {
90569063
return posix_error();
90579064
}
9065+
90589066
return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
90599067
}
90609068
#endif /* HAVE_FORKPTY */

0 commit comments

Comments
 (0)