Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Lib/test/test_pty.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
raise unittest.SkipTest("pty is not available on this platform")

import errno
import fcntl
import os
import pty
import tty
Expand Down Expand Up @@ -230,6 +231,10 @@ def test_fork(self):
os._exit(2)
os._exit(4)
else:
flags = fcntl.fcntl(master_fd, fcntl.F_GETFD)
cloexec_set = bool(flags & fcntl.FD_CLOEXEC)
flags = fcntl.fcntl(master_fd, fcntl.F_GETFD)
self.assertTrue(flags & fcntl.FD_CLOEXEC)
debug("Waiting for child (%d) to finish." % pid)
# In verbose mode, we have to consume the debug output from the
# child or the child will block, causing this test to hang in the
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Set O_CLOEXEC for master_fd when call os.forkpty
8 changes: 8 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -9059,14 +9059,22 @@ os_forkpty_impl(PyObject *module)
} else {
/* parent: release the import lock. */
PyOS_AfterFork_Parent();
/* set O_CLOEXEC on master_fd */
if (_Py_set_inheritable(master_fd, 0, NULL) < 0)
goto error;
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
if (warn_about_fork_with_threads("forkpty") < 0)
return NULL;
}
if (pid == -1) {
return posix_error();
}

return Py_BuildValue("(Ni)", PyLong_FromPid(pid), master_fd);
error:
if (master_fd != -1)
close(master_fd);
return NULL;
}
#endif /* HAVE_FORKPTY */

Expand Down
Loading