Skip to content

Commit a0caab9

Browse files
gh-154225: Fix os.openpty() acquiring a controlling terminal on Solaris (GH-154229)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent d01b90c commit a0caab9

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
@@ -9431,11 +9431,30 @@ os_openpty_impl(PyObject *module)
94319431
goto posix_error;
94329432

94339433
#if defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC)
9434+
// Pushing "ptem" makes the slave a terminal, which a session leader
9435+
// without a controlling terminal then acquires as one despite O_NOCTTY.
9436+
// Note whether we already had one, so a new one can be disowned below.
9437+
int had_ctty = 0;
9438+
#ifdef TIOCNOTTY
9439+
int tty_fd = open("/dev/tty", O_RDONLY | O_NOCTTY);
9440+
if (tty_fd >= 0) {
9441+
had_ctty = 1;
9442+
close(tty_fd);
9443+
}
9444+
#endif
94349445
ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
94359446
ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
94369447
#ifndef __hpux
94379448
ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
94389449
#endif /* __hpux */
9450+
#ifdef TIOCNOTTY
9451+
if (!had_ctty && getsid(0) == getpid()) {
9452+
// Disown it; TIOCNOTTY sends SIGHUP to the session leader.
9453+
PyOS_sighandler_t sig_saved = PyOS_setsig(SIGHUP, SIG_IGN);
9454+
ioctl(slave_fd, TIOCNOTTY);
9455+
PyOS_setsig(SIGHUP, sig_saved);
9456+
}
9457+
#endif
94399458
#endif /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
94409459
#endif /* HAVE_OPENPTY */
94419460

0 commit comments

Comments
 (0)