]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-154345: Fix test_posix_pty_functions() killing the worker on Solaris (GH-154346)
authorSerhiy Storchaka <storchaka@gmail.com>
Tue, 21 Jul 2026 13:12:20 +0000 (16:12 +0300)
committerGitHub <noreply@github.com>
Tue, 21 Jul 2026 13:12:20 +0000 (16:12 +0300)
Pushing the "ptem" STREAMS module makes a session leader without a
controlling terminal acquire the slave as one, so closing the file
descriptors sent SIGHUP to the session and killed the regrtest worker.
Disown it after the pushes, as os.openpty() does.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Lib/test/test_os/test_os.py

index 41928b308c477992349374126d10f2a35ae49074..b4310043b60178b2aa678e5e1f2206904f0b4460 100644 (file)
@@ -4728,12 +4728,27 @@ class PseudoterminalTests(unittest.TestCase):
         son_fd = os.open(son_path, os.O_RDWR|os.O_NOCTTY)
         self.addCleanup(os.close, son_fd)
         if sys.platform.startswith('sunos'):
-            # The slave is not a terminal until these STREAMS modules
-            # are pushed onto it.
             import fcntl
             I_PUSH = 0x5302
+            TIOCNOTTY = 0x7471
+            # 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.
+            try:
+                os.close(os.open('/dev/tty', os.O_RDONLY|os.O_NOCTTY))
+                had_ctty = True
+            except OSError:
+                had_ctty = False
             fcntl.ioctl(son_fd, I_PUSH, b'ptem\0')
             fcntl.ioctl(son_fd, I_PUSH, b'ldterm\0')
+            if not had_ctty and os.getsid(0) == os.getpid():
+                # Disown it, otherwise closing the file descriptors sends
+                # SIGHUP to the session.  TIOCNOTTY sends it too.
+                old_handler = signal.signal(signal.SIGHUP, signal.SIG_IGN)
+                try:
+                    fcntl.ioctl(son_fd, TIOCNOTTY)
+                finally:
+                    signal.signal(signal.SIGHUP, old_handler)
         self.assertEqual(os.ptsname(mother_fd), os.ttyname(son_fd))
 
     @warnings_helper.ignore_fork_in_thread_deprecation_warnings()