Skip to content

Commit 76b5867

Browse files
[3.13] gh-154225: Fix os.openpty() acquiring a controlling terminal on Solaris (GH-154229) (GH-154257)
(cherry picked from commit a0caab9) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 9f5fe6b commit 76b5867

2 files changed

Lines changed: 21 additions & 0 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :func:`os.openpty` on Solaris and illumos: it no longer leaves the
2+
pseudo-terminal as the controlling terminal of the calling process.

Modules/posixmodule.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8863,11 +8863,30 @@ os_openpty_impl(PyObject *module)
88638863
goto posix_error;
88648864

88658865
#if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
8866+
// Pushing "ptem" makes the slave a terminal, which a session leader
8867+
// without a controlling terminal then acquires as one despite O_NOCTTY.
8868+
// Note whether we already had one, so a new one can be disowned below.
8869+
int had_ctty = 0;
8870+
#ifdef TIOCNOTTY
8871+
int tty_fd = open("/dev/tty", O_RDONLY | O_NOCTTY);
8872+
if (tty_fd >= 0) {
8873+
had_ctty = 1;
8874+
close(tty_fd);
8875+
}
8876+
#endif
88668877
ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
88678878
ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
88688879
#ifndef __hpux
88698880
ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
88708881
#endif /* __hpux */
8882+
#ifdef TIOCNOTTY
8883+
if (!had_ctty && getsid(0) == getpid()) {
8884+
// Disown it; TIOCNOTTY sends SIGHUP to the session leader.
8885+
PyOS_sighandler_t sig_saved = PyOS_setsig(SIGHUP, SIG_IGN);
8886+
ioctl(slave_fd, TIOCNOTTY);
8887+
PyOS_setsig(SIGHUP, sig_saved);
8888+
}
8889+
#endif
88718890
#endif /* HAVE_CYGWIN */
88728891
#endif /* HAVE_OPENPTY */
88738892

0 commit comments

Comments
 (0)