]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.15] gh-150436: Skip subprocess test on STATUS_DLL_INIT_FAILED (GH-150704) (#150713)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Thu, 4 Jun 2026 08:46:08 +0000 (10:46 +0200)
committerGitHub <noreply@github.com>
Thu, 4 Jun 2026 08:46:08 +0000 (08:46 +0000)
gh-150436: Skip subprocess test on STATUS_DLL_INIT_FAILED (GH-150704)

If a subprocess spawned with CREATE_NEW_CONSOLE creation flag fails
with STATUS_DLL_INIT_FAILED return code, skip the test. It's likely a
memory allocation failure in the desktop heap memory which caused the
DLL init failure.
(cherry picked from commit e8034dd841808416e243a4b2f8e08f0edf9caff3)

Co-authored-by: Victor Stinner <vstinner@python.org>
Lib/test/support/__init__.py
Lib/test/test_cmd_line.py
Lib/test/test_msvcrt.py
Lib/test/test_subprocess.py

index 2cac70f4ab2afbef9a719ec8aff3f3ceb439a264..f9601655dfe157a982db088fd3e77d803b04c0c3 100644 (file)
@@ -3323,3 +3323,18 @@ def control_characters_c0() -> list[str]:
 _ROOT_IN_POSIX = hasattr(os, 'geteuid') and os.geteuid() == 0
 requires_root_user = unittest.skipUnless(_ROOT_IN_POSIX, "test needs root privilege")
 requires_non_root_user = unittest.skipIf(_ROOT_IN_POSIX, "test needs non-root account")
+
+
+STATUS_DLL_INIT_FAILED = 0xC0000142
+def skip_on_low_desktop_heap_memory_subprocess(returncode):
+    if sys.platform not in ('win32', 'cygwin'):
+        return
+    # On Windows, STATUS_DLL_INIT_FAILED is a generic error code that could
+    # come from any of the DLLs being loaded when a new Python process is
+    # created. In practice, it's likely a memory allocation failure in the
+    # desktop heap memory which caused the DLL init failure, especially on
+    # process created with CREATE_NEW_CONSOLE creation flag. See the article:
+    # https://learn.microsoft.com/en-us/troubleshoot/windows-server/performance/desktop-heap-limitation-out-of-memory
+    if returncode == STATUS_DLL_INIT_FAILED:
+        raise unittest.SkipTest('gh-150436: DLL init failed, likely because '
+                                'of low desktop heap memory')
index 7f9e44d70001b75f3f45b2c050191d00c9e4422e..3b556ec31445dfbf87650b682fec0f04a0607f10 100644 (file)
@@ -1036,6 +1036,7 @@ class CmdLineTest(unittest.TestCase):
         p = subprocess.run([sys.executable, "-c", code],
                            creationflags=subprocess.CREATE_NEW_CONSOLE,
                            env=env)
+        support.skip_on_low_desktop_heap_memory_subprocess(p.returncode)
         self.assertEqual(p.returncode, 0)
 
         # Then test that FIleIO is used when PYTHONLEGACYWINDOWSSTDIO is set.
@@ -1044,6 +1045,7 @@ class CmdLineTest(unittest.TestCase):
         p = subprocess.run([sys.executable, "-c", code],
                            creationflags=subprocess.CREATE_NEW_CONSOLE,
                            env=env)
+        support.skip_on_low_desktop_heap_memory_subprocess(p.returncode)
         self.assertEqual(p.returncode, 0)
 
     @unittest.skipIf("-fsanitize" in sysconfig.get_config_vars().get('PY_CFLAGS', ()),
index 1c6905bd1ee5864b091a4d19e461228fb278ec62..fef86ce323e54d55f1d9989b3b59b9fa6b0a99a0 100644 (file)
@@ -4,6 +4,7 @@ import sys
 import unittest
 from textwrap import dedent
 
+from test import support
 from test.support import os_helper, requires_resource
 from test.support.os_helper import TESTFN, TESTFN_ASCII
 
@@ -67,8 +68,12 @@ class TestConsoleIO(unittest.TestCase):
         # Run test in a separated process to avoid stdin conflicts.
         # See: gh-110147
         cmd = [sys.executable, '-c', code]
-        subprocess.run(cmd, check=True, capture_output=True,
-                       creationflags=subprocess.CREATE_NEW_CONSOLE)
+        try:
+            subprocess.run(cmd, check=True, capture_output=True,
+                           creationflags=subprocess.CREATE_NEW_CONSOLE)
+        except subprocess.CalledProcessError as exc:
+            support.skip_on_low_desktop_heap_memory_subprocess(exc.returncode)
+            raise
 
     def test_kbhit(self):
         code = dedent('''
index 1a3db527d3d5b83667ac5d1876fa6cef0b21c3cc..f944084aaa6d6aa88f0ecda2f83e2b7154835a68 100644 (file)
@@ -3765,13 +3765,17 @@ class Win32ProcessTestCase(BaseTestCase):
             self.assertEqual(startupinfo.wShowWindow, subprocess.SW_HIDE)
             self.assertEqual(startupinfo.lpAttributeList, {"handle_list": []})
 
+    # CREATE_NEW_CONSOLE creates a "popup" window.
+    @support.requires_resource('gui')
     def test_creationflags(self):
         # creationflags argument
         CREATE_NEW_CONSOLE = 16
         sys.stderr.write("    a DOS box should flash briefly ...\n")
-        subprocess.call(sys.executable +
-                        ' -c "import time; time.sleep(0.25)"',
-                        creationflags=CREATE_NEW_CONSOLE)
+        rc = subprocess.call(sys.executable +
+                             ' -c "import time; time.sleep(0.25)"',
+                             creationflags=CREATE_NEW_CONSOLE)
+        support.skip_on_low_desktop_heap_memory_subprocess(rc)
+        self.assertEqual(rc, 0)
 
     def test_invalid_args(self):
         # invalid arguments should raise ValueError