Unverified Kaydet (Commit) 483422f5 authored tarafından Victor Stinner's avatar Victor Stinner Kaydeden (comit) GitHub

bpo-34044: subprocess.Popen copies startupinfo (GH-8090)

subprocess.Popen now copies the startupinfo argument to leave it
unchanged: it will modify the copy, so that the same STARTUPINFO
object can be used multiple times.

Add subprocess.STARTUPINFO.copy() method.
üst 09bb918a
...@@ -135,6 +135,19 @@ if _mswindows: ...@@ -135,6 +135,19 @@ if _mswindows:
self.hStdError = hStdError self.hStdError = hStdError
self.wShowWindow = wShowWindow self.wShowWindow = wShowWindow
self.lpAttributeList = lpAttributeList or {"handle_list": []} self.lpAttributeList = lpAttributeList or {"handle_list": []}
def copy(self):
attr_list = self.lpAttributeList.copy()
if 'handle_list' in attr_list:
attr_list['handle_list'] = list(attr_list['handle_list'])
return STARTUPINFO(dwFlags=self.dwFlags,
hStdInput=self.hStdInput,
hStdOutput=self.hStdOutput,
hStdError=self.hStdError,
wShowWindow=self.wShowWindow,
lpAttributeList=attr_list)
else: else:
import _posixsubprocess import _posixsubprocess
import select import select
...@@ -1102,6 +1115,10 @@ class Popen(object): ...@@ -1102,6 +1115,10 @@ class Popen(object):
# Process startup details # Process startup details
if startupinfo is None: if startupinfo is None:
startupinfo = STARTUPINFO() startupinfo = STARTUPINFO()
else:
# bpo-34044: Copy STARTUPINFO since it is modified above,
# so the caller can reuse it multiple times.
startupinfo = startupinfo.copy()
use_std_handles = -1 not in (p2cread, c2pwrite, errwrite) use_std_handles = -1 not in (p2cread, c2pwrite, errwrite)
if use_std_handles: if use_std_handles:
......
...@@ -2822,6 +2822,33 @@ class Win32ProcessTestCase(BaseTestCase): ...@@ -2822,6 +2822,33 @@ class Win32ProcessTestCase(BaseTestCase):
subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"], subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"],
startupinfo=startupinfo) startupinfo=startupinfo)
def test_startupinfo_copy(self):
# bpo-34044: Popen must not modify input STARTUPINFO structure
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags = subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = subprocess.SW_HIDE
# Call Popen() twice with the same startupinfo object to make sure
# that it's not modified
for _ in range(2):
cmd = [sys.executable, "-c", "pass"]
with open(os.devnull, 'w') as null:
proc = subprocess.Popen(cmd,
stdout=null,
stderr=subprocess.STDOUT,
startupinfo=startupinfo)
with proc:
proc.communicate()
self.assertEqual(proc.returncode, 0)
self.assertEqual(startupinfo.dwFlags,
subprocess.STARTF_USESHOWWINDOW)
self.assertIsNone(startupinfo.hStdInput)
self.assertIsNone(startupinfo.hStdOutput)
self.assertIsNone(startupinfo.hStdError)
self.assertEqual(startupinfo.wShowWindow, subprocess.SW_HIDE)
self.assertEqual(startupinfo.lpAttributeList, {"handle_list": []})
def test_creationflags(self): def test_creationflags(self):
# creationflags argument # creationflags argument
CREATE_NEW_CONSOLE = 16 CREATE_NEW_CONSOLE = 16
......
``subprocess.Popen`` now copies the *startupinfo* argument to leave it
unchanged: it will modify the copy, so that the same ``STARTUPINFO`` object can
be used multiple times.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment