]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-154225: Fix os.openpty() acquiring a controlling terminal on Solaris (GH...
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 20 Jul 2026 13:11:32 +0000 (16:11 +0300)
committerGitHub <noreply@github.com>
Mon, 20 Jul 2026 13:11:32 +0000 (13:11 +0000)
(cherry picked from commit a0caab9db6c2655d8429279892848d817343f99d)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Misc/NEWS.d/next/Library/2026-07-20-14-10-00.gh-issue-154225.openpty.rst [new file with mode: 0644]
Modules/posixmodule.c

diff --git a/Misc/NEWS.d/next/Library/2026-07-20-14-10-00.gh-issue-154225.openpty.rst b/Misc/NEWS.d/next/Library/2026-07-20-14-10-00.gh-issue-154225.openpty.rst
new file mode 100644 (file)
index 0000000..f15022b
--- /dev/null
@@ -0,0 +1,2 @@
+Fix :func:`os.openpty` on Solaris and illumos: it no longer leaves the
+pseudo-terminal as the controlling terminal of the calling process.
index debe861b139ade6da4e5a2d4f9be68042b8f32b6..06928025490ac8aaa39b6592c6b8cd00c5f18db4 100644 (file)
@@ -8960,11 +8960,30 @@ os_openpty_impl(PyObject *module)
         goto posix_error;
 
 #if !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(HAVE_DEV_PTC)
+    // Pushing "ptem" makes the slave a terminal, which a session leader
+    // without a controlling terminal then acquires as one despite O_NOCTTY.
+    // Note whether we already had one, so a new one can be disowned below.
+    int had_ctty = 0;
+#ifdef TIOCNOTTY
+    int tty_fd = open("/dev/tty", O_RDONLY | O_NOCTTY);
+    if (tty_fd >= 0) {
+        had_ctty = 1;
+        close(tty_fd);
+    }
+#endif
     ioctl(slave_fd, I_PUSH, "ptem"); /* push ptem */
     ioctl(slave_fd, I_PUSH, "ldterm"); /* push ldterm */
 #ifndef __hpux
     ioctl(slave_fd, I_PUSH, "ttcompat"); /* push ttcompat */
 #endif /* __hpux */
+#ifdef TIOCNOTTY
+    if (!had_ctty && getsid(0) == getpid()) {
+        // Disown it; TIOCNOTTY sends SIGHUP to the session leader.
+        PyOS_sighandler_t sig_saved = PyOS_setsig(SIGHUP, SIG_IGN);
+        ioctl(slave_fd, TIOCNOTTY);
+        PyOS_setsig(SIGHUP, sig_saved);
+    }
+#endif
 #endif /* HAVE_CYGWIN */
 #endif /* HAVE_OPENPTY */