--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/python27/patches/30-pty.patch Wed Apr 26 13:55:01 2017 -0700
@@ -0,0 +1,64 @@
+This patch comes from upstream: http://bugs.python.org/issue26228
+It has not yet been committed, but seems on track to be, and we need
+it to fix a bug.
+
+--- Python-2.7.13/Lib/pty.py.orig 2016-12-17 12:05:06.000000000 -0800
++++ Python-2.7.13/Lib/pty.py 2017-04-26 13:34:02.125867738 -0700
[email protected]@ -148,7 +148,7 @@
+ if master_fd in rfds:
+ data = master_read(master_fd)
+ if not data: # Reached EOF.
+- fds.remove(master_fd)
++ return
+ else:
+ os.write(STDOUT_FILENO, data)
+ if STDIN_FILENO in rfds:
[email protected]@ -164,7 +164,15 @@
+ argv = (argv,)
+ pid, master_fd = fork()
+ if pid == CHILD:
+- os.execlp(argv[0], *argv)
++ try:
++ os.execlp(argv[0], *argv)
++ except:
++ # If we wanted to be really clever, we would use
++ # the same method as subprocess() to pass the error
++ # back to the parent. For now just dump stack trace.
++ traceback.print_exc()
++ finally:
++ os._exit(1)
+ try:
+ mode = tty.tcgetattr(STDIN_FILENO)
+ tty.setraw(STDIN_FILENO)
[email protected]@ -174,6 +182,10 @@
+ try:
+ _copy(master_fd, master_read, stdin_read)
+ except (IOError, OSError):
++ # Some OSes never return an EOF on pty, just raise
++ # an error instead.
++ pass
++ finally:
+ if restore:
+ tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+--- Python-2.7.13/Lib/test/test_pty.py.orig 2016-12-17 12:05:06.000000000 +0000
++++ Python-2.7.13/Lib/test/test_pty.py 2017-04-26 13:39:11.397817862 +0000
[email protected]@ -270,7 +270,7 @@
+ socketpair[1].close()
+ os.close(write_to_stdin_fd)
+
+- # Expect two select calls, the last one will cause IndexError
++ # Expect two select calls, then a normal return on master EOF
+ pty.select = self._mock_select
+ self.select_rfds_lengths.append(2)
+ self.select_rfds_results.append([mock_stdin_fd, masters[0]])
[email protected]@ -278,8 +278,7 @@
+ # both encountered an EOF before the second select call.
+ self.select_rfds_lengths.append(0)
+
+- with self.assertRaises(IndexError):
+- pty._copy(masters[0])
++ pty._copy(masters[0])
+
+
+ def test_main(verbose=None):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/python34/patches/28-pty.patch Wed Apr 26 13:55:01 2017 -0700
@@ -0,0 +1,64 @@
+This patch comes from upstream: http://bugs.python.org/issue26228
+It has not yet been committed, but seems on track to be, and we need
+it to fix a bug.
+
+--- Python-3.4.6/Lib/pty.py.~1~ 2017-01-16 23:57:41.000000000 +0000
++++ Python-3.4.6/Lib/pty.py 2017-04-26 13:42:05.837992313 +0000
[email protected]@ -137,7 +137,7 @@
+ if master_fd in rfds:
+ data = master_read(master_fd)
+ if not data: # Reached EOF.
+- fds.remove(master_fd)
++ return
+ else:
+ os.write(STDOUT_FILENO, data)
+ if STDIN_FILENO in rfds:
[email protected]@ -153,7 +153,15 @@
+ argv = (argv,)
+ pid, master_fd = fork()
+ if pid == CHILD:
+- os.execlp(argv[0], *argv)
++ try:
++ os.execlp(argv[0], *argv)
++ except:
++ # If we wanted to be really clever, we would use
++ # the same method as subprocess() to pass the error
++ # back to the parent. For now just dump stack trace.
++ traceback.print_exc()
++ finally:
++ os._exit(1)
+ try:
+ mode = tty.tcgetattr(STDIN_FILENO)
+ tty.setraw(STDIN_FILENO)
[email protected]@ -163,6 +171,10 @@
+ try:
+ _copy(master_fd, master_read, stdin_read)
+ except OSError:
++ # Some OSes never return an EOF on pty, just raise
++ # an error instead.
++ pass
++ finally:
+ if restore:
+ tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+--- Python-3.4.6/Lib/test/test_pty.py.~1~ 2017-01-16 23:57:43.000000000 +0000
++++ Python-3.4.6/Lib/test/test_pty.py 2017-04-26 13:42:05.838370945 +0000
[email protected]@ -280,7 +280,7 @@
+ socketpair[1].close()
+ os.close(write_to_stdin_fd)
+
+- # Expect two select calls, the last one will cause IndexError
++ # Expect two select calls, then a normal return on master EOF
+ pty.select = self._mock_select
+ self.select_rfds_lengths.append(2)
+ self.select_rfds_results.append([mock_stdin_fd, masters[0]])
[email protected]@ -288,8 +288,7 @@
+ # both encountered an EOF before the second select call.
+ self.select_rfds_lengths.append(0)
+
+- with self.assertRaises(IndexError):
+- pty._copy(masters[0])
++ pty._copy(masters[0])
+
+
+ def test_main(verbose=None):
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/components/python/python35/patches/31-pty.patch Wed Apr 26 13:55:01 2017 -0700
@@ -0,0 +1,64 @@
+This patch comes from upstream: http://bugs.python.org/issue26228
+It has not yet been committed, but seems on track to be, and we need
+it to fix a bug.
+
+--- Python-3.5.3/Lib/pty.py.~1~ 2017-01-16 23:57:49.000000000 +0000
++++ Python-3.5.3/Lib/pty.py 2017-04-26 13:49:30.528312446 +0000
[email protected]@ -137,7 +137,7 @@
+ if master_fd in rfds:
+ data = master_read(master_fd)
+ if not data: # Reached EOF.
+- fds.remove(master_fd)
++ return
+ else:
+ os.write(STDOUT_FILENO, data)
+ if STDIN_FILENO in rfds:
[email protected]@ -153,7 +153,15 @@
+ argv = (argv,)
+ pid, master_fd = fork()
+ if pid == CHILD:
+- os.execlp(argv[0], *argv)
++ try:
++ os.execlp(argv[0], *argv)
++ except:
++ # If we wanted to be really clever, we would use
++ # the same method as subprocess() to pass the error
++ # back to the parent. For now just dump stack trace.
++ traceback.print_exc()
++ finally:
++ os._exit(1)
+ try:
+ mode = tty.tcgetattr(STDIN_FILENO)
+ tty.setraw(STDIN_FILENO)
[email protected]@ -163,6 +171,10 @@
+ try:
+ _copy(master_fd, master_read, stdin_read)
+ except OSError:
++ # Some OSes never return an EOF on pty, just raise
++ # an error instead.
++ pass
++ finally:
+ if restore:
+ tty.tcsetattr(STDIN_FILENO, tty.TCSAFLUSH, mode)
+
+--- Python-3.5.3/Lib/test/test_pty.py.~1~ 2017-01-16 23:57:51.000000000 +0000
++++ Python-3.5.3/Lib/test/test_pty.py 2017-04-26 13:50:25.073451009 +0000
[email protected]@ -281,7 +281,7 @@
+ socketpair[1].close()
+ os.close(write_to_stdin_fd)
+
+- # Expect two select calls, the last one will cause IndexError
++ # Expect two select calls, then a normal return on master EOF
+ pty.select = self._mock_select
+ self.select_rfds_lengths.append(2)
+ self.select_rfds_results.append([mock_stdin_fd, masters[0]])
[email protected]@ -289,8 +289,7 @@
+ # both encountered an EOF before the second select call.
+ self.select_rfds_lengths.append(0)
+
+- with self.assertRaises(IndexError):
+- pty._copy(masters[0])
++ pty._copy(masters[0])
+
+
+ def tearDownModule():