[3.6] bpo-30121: Fix debug assert in subprocess on Windows (#1224) (#… · python/cpython@e76cb43 (original) (raw)

`@@ -49,6 +49,8 @@

`

49

49

`else:

`

50

50

`SETBINARY = ''

`

51

51

``

``

52

`+

NONEXISTING_CMD = ('nonexisting_i_hope',)

`

``

53

+

52

54

``

53

55

`class BaseTestCase(unittest.TestCase):

`

54

56

`def setUp(self):

`

`@@ -1120,10 +1122,11 @@ def _test_bufsize_equal_one(self, line, expected, universal_newlines):

`

1120

1122

`p.stdin.write(line) # expect that it flushes the line in text mode

`

1121

1123

`os.close(p.stdin.fileno()) # close it without flushing the buffer

`

1122

1124

`read_line = p.stdout.readline()

`

1123

``

`-

try:

`

1124

``

`-

p.stdin.close()

`

1125

``

`-

except OSError:

`

1126

``

`-

pass

`

``

1125

`+

with support.SuppressCrashReport():

`

``

1126

`+

try:

`

``

1127

`+

p.stdin.close()

`

``

1128

`+

except OSError:

`

``

1129

`+

pass

`

1127

1130

`p.stdin = None

`

1128

1131

`self.assertEqual(p.returncode, 0)

`

1129

1132

`self.assertEqual(read_line, expected)

`

`@@ -1148,13 +1151,54 @@ def test_leaking_fds_on_error(self):

`

1148

1151

`# 1024 times (each call leaked two fds).

`

1149

1152

`for i in range(1024):

`

1150

1153

`with self.assertRaises(OSError) as c:

`

1151

``

`-

subprocess.Popen(['nonexisting_i_hope'],

`

``

1154

`+

subprocess.Popen(NONEXISTING_CMD,

`

1152

1155

`stdout=subprocess.PIPE,

`

1153

1156

`stderr=subprocess.PIPE)

`

1154

1157

`# ignore errors that indicate the command was not found

`

1155

1158

`if c.exception.errno not in (errno.ENOENT, errno.EACCES):

`

1156

1159

`raise c.exception

`

1157

1160

``

``

1161

`+

def test_nonexisting_with_pipes(self):

`

``

1162

`+

bpo-30121: Popen with pipes must close properly pipes on error.

`

``

1163

`+

Previously, os.close() was called with a Windows handle which is not

`

``

1164

`+

a valid file descriptor.

`

``

1165

`+

`

``

1166

`+

Run the test in a subprocess to control how the CRT reports errors

`

``

1167

`+

and to get stderr content.

`

``

1168

`+

try:

`

``

1169

`+

import msvcrt

`

``

1170

`+

msvcrt.CrtSetReportMode

`

``

1171

`+

except (AttributeError, ImportError):

`

``

1172

`+

self.skipTest("need msvcrt.CrtSetReportMode")

`

``

1173

+

``

1174

`+

code = textwrap.dedent(f"""

`

``

1175

`+

import msvcrt

`

``

1176

`+

import subprocess

`

``

1177

+

``

1178

`+

cmd = {NONEXISTING_CMD!r}

`

``

1179

+

``

1180

`+

for report_type in [msvcrt.CRT_WARN,

`

``

1181

`+

msvcrt.CRT_ERROR,

`

``

1182

`+

msvcrt.CRT_ASSERT]:

`

``

1183

`+

msvcrt.CrtSetReportMode(report_type, msvcrt.CRTDBG_MODE_FILE)

`

``

1184

`+

msvcrt.CrtSetReportFile(report_type, msvcrt.CRTDBG_FILE_STDERR)

`

``

1185

+

``

1186

`+

try:

`

``

1187

`+

subprocess.Popen([cmd],

`

``

1188

`+

stdout=subprocess.PIPE,

`

``

1189

`+

stderr=subprocess.PIPE)

`

``

1190

`+

except OSError:

`

``

1191

`+

pass

`

``

1192

`+

""")

`

``

1193

`+

cmd = [sys.executable, "-c", code]

`

``

1194

`+

proc = subprocess.Popen(cmd,

`

``

1195

`+

stderr=subprocess.PIPE,

`

``

1196

`+

universal_newlines=True)

`

``

1197

`+

with proc:

`

``

1198

`+

stderr = proc.communicate()[1]

`

``

1199

`+

self.assertEqual(stderr, "")

`

``

1200

`+

self.assertEqual(proc.returncode, 0)

`

``

1201

+

1158

1202

`@unittest.skipIf(threading is None, "threading required")

`

1159

1203

`def test_double_close_on_error(self):

`

1160

1204

`# Issue #18851

`

`@@ -1167,7 +1211,7 @@ def open_fds():

`

1167

1211

`t.start()

`

1168

1212

`try:

`

1169

1213

`with self.assertRaises(EnvironmentError):

`

1170

``

`-

subprocess.Popen(['nonexisting_i_hope'],

`

``

1214

`+

subprocess.Popen(NONEXISTING_CMD,

`

1171

1215

`stdin=subprocess.PIPE,

`

1172

1216

`stdout=subprocess.PIPE,

`

1173

1217

`stderr=subprocess.PIPE)

`

`@@ -2433,7 +2477,7 @@ def test_leak_fast_process_del_killed(self):

`

2433

2477

`# should trigger the wait() of p

`

2434

2478

`time.sleep(0.2)

`

2435

2479

`with self.assertRaises(OSError) as c:

`

2436

``

`-

with subprocess.Popen(['nonexisting_i_hope'],

`

``

2480

`+

with subprocess.Popen(NONEXISTING_CMD,

`

2437

2481

`stdout=subprocess.PIPE,

`

2438

2482

`stderr=subprocess.PIPE) as proc:

`

2439

2483

`pass

`

`@@ -2863,7 +2907,7 @@ def test_communicate_stdin(self):

`

2863

2907

``

2864

2908

`def test_invalid_args(self):

`

2865

2909

`with self.assertRaises((FileNotFoundError, PermissionError)) as c:

`

2866

``

`-

with subprocess.Popen(['nonexisting_i_hope'],

`

``

2910

`+

with subprocess.Popen(NONEXISTING_CMD,

`

2867

2911

`stdout=subprocess.PIPE,

`

2868

2912

`stderr=subprocess.PIPE) as proc:

`

2869

2913

`pass

`