]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.15] gh-154345: Fix test_posix_pty_functions() killing the worker on Solaris (GH...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 21 Jul 2026 14:49:13 +0000 (16:49 +0200)
committerGitHub <noreply@github.com>
Tue, 21 Jul 2026 14:49:13 +0000 (17:49 +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.
(cherry picked from commit f69f7fd526b6601a74ce0852c75466a183a86cea)

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

index f2b9cf75d3bfa15a0a274b8dd95dcac1c4d47689..6be86ac56a0d1f18a6fd0d4abc6995dd312a99e3 100644 (file)
@@ -4716,12 +4716,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()