[3.15] gh-154225: Fix os.openpty() acquiring a controlling terminal on Solaris (GH-154229) (GH-154238)

serhiy-storchaka <[email protected]>
Newsgroups gmane.comp.python.cvs
Message-ID <[email protected]>
https://github.com/python/cpython/commit/2aee2faff41046c351580f092e596a163489e000
commit: 2aee2faff41046c351580f092e596a163489e000
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-07-20T12:40:40+03:00
summary:

[3.15] gh-154225: Fix os.openpty() acquiring a controlling terminal on Solaris (GH-154229) (GH-154238)

(cherry picked from commit a0caab9db6c2655d8429279892848d817343f99d)

Co-authored-by: Serhiy Storchaka <[email protected]>
Co-authored-by: Claude Fable 5 <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-07-20-14-10-00.gh-issue-154225.openpty.rst
M 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
index 00000000000000..f15022b6632006
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-07-20-14-10-00.gh-issue-154225.openpty.rst
@@ -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.
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 2a25be16e61dc2..b4009b8cb68694 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -9429,11 +9429,30 @@ os_openpty_impl(PyObject *module)
         goto posix_error;
 
 #if defined(HAVE_STROPTS_H) && !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 /* defined(HAVE_STROPTS_H) && !defined(HAVE_DEV_PTC) */
 #endif /* HAVE_OPENPTY */
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.