]> granicus.if.org Git - python/commitdiff
bpo-37549: os.dup() fails for standard streams on Windows 7 (GH-15389)
authorZackery Spytz <zspytz@gmail.com>
Fri, 23 Aug 2019 18:38:41 +0000 (12:38 -0600)
committerSteve Dower <steve.dower@python.org>
Fri, 23 Aug 2019 18:38:41 +0000 (11:38 -0700)
Lib/test/test_os.py
Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst [new file with mode: 0644]
Python/fileutils.c

index 4285931512085902caba82cce6cd04f21a49720e..440cd6c1cf73c3b0ffb4b3a21b7d96f8ebcedfdd 100644 (file)
@@ -3476,6 +3476,11 @@ class FDInheritanceTests(unittest.TestCase):
         self.addCleanup(os.close, fd2)
         self.assertEqual(os.get_inheritable(fd2), False)
 
+    def test_dup_standard_stream(self):
+        fd = os.dup(1)
+        self.addCleanup(os.close, fd)
+        self.assertGreater(fd, 0)
+
     @unittest.skipUnless(sys.platform == 'win32', 'win32-specific test')
     def test_dup_nul(self):
         # os.dup() was creating inheritable fds for character files.
diff --git a/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst b/Misc/NEWS.d/next/Windows/2019-08-22-09-04-44.bpo-37549.TpKI3M.rst
new file mode 100644 (file)
index 0000000..5345da8
--- /dev/null
@@ -0,0 +1 @@
+:func:`os.dup` no longer fails for standard streams on Windows 7.
index 36a3c995a98a92220449a86cb421ac10dead5e57..0c05424143afb5a3406b737e09869375eacdee76 100644 (file)
@@ -1134,11 +1134,18 @@ set_inheritable(int fd, int inheritable, int raise, int *atomic_flag_works)
         flags = HANDLE_FLAG_INHERIT;
     else
         flags = 0;
-    if (!SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
+
+    /* This check can be removed once support for Windows 7 ends. */
+#define CONSOLE_PSEUDOHANDLE(handle) (((ULONG_PTR)(handle) & 0x3) == 0x3 && \
+        GetFileType(handle) == FILE_TYPE_CHAR)
+
+    if (!CONSOLE_PSEUDOHANDLE(handle) &&
+        !SetHandleInformation(handle, HANDLE_FLAG_INHERIT, flags)) {
         if (raise)
             PyErr_SetFromWindowsErr(0);
         return -1;
     }
+#undef CONSOLE_PSEUDOHANDLE
     return 0;
 
 #else