blob: 45ba37352d23acb5eb97f0b85c7539a6922ca450 [file] [log] [blame]
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001import unittest
Chris Jerdonekec3ea942012-09-30 00:10:28 -07002from test import script_helper
Benjamin Petersonee8712c2008-05-20 21:35:26 +00003from test import support
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00004import subprocess
5import sys
6import signal
Gregory P. Smithe14e9c22011-03-15 14:55:17 -04007import io
Andrew Svetlov82860712012-08-19 22:13:41 +03008import locale
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00009import os
Gregory P. Smitha59c59f2010-03-01 00:17:40 +000010import errno
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000011import tempfile
12import time
Tim Peters3761e8d2004-10-13 04:07:12 +000013import re
Ezio Melotti184bdfb2010-02-18 09:37:05 +000014import sysconfig
Gregory P. Smithd23047b2010-12-04 09:10:44 +000015import warnings
Gregory P. Smith51ee2702010-12-13 07:59:39 +000016import select
Gregory P. Smith81ce6852011-03-15 02:04:11 -040017import shutil
Benjamin Petersonb870aa12011-12-10 12:44:25 -050018import gc
Benjamin Peterson964561b2011-12-10 12:31:42 -050019
20try:
21 import resource
22except ImportError:
23 resource = None
24
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000025mswindows = (sys.platform == "win32")
26
27#
28# Depends on the following external programs: Python
29#
30
31if mswindows:
Tim Peters3b01a702004-10-12 22:19:32 +000032 SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), '
33 'os.O_BINARY);')
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000034else:
35 SETBINARY = ''
36
Florent Xiclunab1e94e82010-02-27 22:12:37 +000037
38try:
39 mkstemp = tempfile.mkstemp
40except AttributeError:
41 # tempfile.mkstemp is not available
42 def mkstemp():
43 """Replacement for mkstemp, calling mktemp."""
44 fname = tempfile.mktemp()
45 return os.open(fname, os.O_RDWR|os.O_CREAT), fname
46
Tim Peters3761e8d2004-10-13 04:07:12 +000047
Florent Xiclunac049d872010-03-27 22:47:23 +000048class BaseTestCase(unittest.TestCase):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000049 def setUp(self):
50 # Try to minimize the number of children we have so this test
51 # doesn't crash on some buildbots (Alphas in particular).
Florent Xiclunab1e94e82010-02-27 22:12:37 +000052 support.reap_children()
Thomas Wouters0e3f5912006-08-11 14:57:12 +000053
Florent Xiclunaf0cbd822010-03-04 21:50:56 +000054 def tearDown(self):
55 for inst in subprocess._active:
56 inst.wait()
57 subprocess._cleanup()
58 self.assertFalse(subprocess._active, "subprocess._active not empty")
59
Florent Xiclunab1e94e82010-02-27 22:12:37 +000060 def assertStderrEqual(self, stderr, expected, msg=None):
61 # In a debug build, stuff like "[6580 refs]" is printed to stderr at
62 # shutdown time. That frustrates tests trying to check stderr produced
63 # from a spawned Python process.
Antoine Pitrou62f68ed2010-08-04 11:48:56 +000064 actual = support.strip_python_stderr(stderr)
Florent Xiclunab1e94e82010-02-27 22:12:37 +000065 self.assertEqual(actual, expected, msg)
Thomas Wouters0e3f5912006-08-11 14:57:12 +000066
Florent Xiclunac049d872010-03-27 22:47:23 +000067
Gregory P. Smith3d8e7762012-11-10 22:32:22 -080068class PopenTestException(Exception):
69 pass
70
71
72class PopenExecuteChildRaises(subprocess.Popen):
73 """Popen subclass for testing cleanup of subprocess.PIPE filehandles when
74 _execute_child fails.
75 """
76 def _execute_child(self, *args, **kwargs):
77 raise PopenTestException("Forced Exception for Test")
78
79
Florent Xiclunac049d872010-03-27 22:47:23 +000080class ProcessTestCase(BaseTestCase):
81
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000082 def test_call_seq(self):
Tim Peters7b759da2004-10-12 22:29:54 +000083 # call() function with sequence argument
Tim Peters3b01a702004-10-12 22:19:32 +000084 rc = subprocess.call([sys.executable, "-c",
85 "import sys; sys.exit(47)"])
Fredrik Lundh5b3687d2004-10-12 15:26:28 +000086 self.assertEqual(rc, 47)
87
Peter Astrand454f7672005-01-01 09:36:35 +000088 def test_check_call_zero(self):
89 # check_call() function with zero return code
90 rc = subprocess.check_call([sys.executable, "-c",
91 "import sys; sys.exit(0)"])
92 self.assertEqual(rc, 0)
93
94 def test_check_call_nonzero(self):
95 # check_call() function with non-zero return code
Florent Xiclunab1e94e82010-02-27 22:12:37 +000096 with self.assertRaises(subprocess.CalledProcessError) as c:
Peter Astrand454f7672005-01-01 09:36:35 +000097 subprocess.check_call([sys.executable, "-c",
98 "import sys; sys.exit(47)"])
Florent Xiclunab1e94e82010-02-27 22:12:37 +000099 self.assertEqual(c.exception.returncode, 47)
Peter Astrand454f7672005-01-01 09:36:35 +0000100
Georg Brandlf9734072008-12-07 15:30:06 +0000101 def test_check_output(self):
102 # check_output() function with zero return code
103 output = subprocess.check_output(
104 [sys.executable, "-c", "print('BDFL')"])
Benjamin Peterson577473f2010-01-19 00:09:57 +0000105 self.assertIn(b'BDFL', output)
Georg Brandlf9734072008-12-07 15:30:06 +0000106
107 def test_check_output_nonzero(self):
108 # check_call() function with non-zero return code
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000109 with self.assertRaises(subprocess.CalledProcessError) as c:
Georg Brandlf9734072008-12-07 15:30:06 +0000110 subprocess.check_output(
111 [sys.executable, "-c", "import sys; sys.exit(5)"])
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000112 self.assertEqual(c.exception.returncode, 5)
Georg Brandlf9734072008-12-07 15:30:06 +0000113
114 def test_check_output_stderr(self):
115 # check_output() function stderr redirected to stdout
116 output = subprocess.check_output(
117 [sys.executable, "-c", "import sys; sys.stderr.write('BDFL')"],
118 stderr=subprocess.STDOUT)
Benjamin Peterson577473f2010-01-19 00:09:57 +0000119 self.assertIn(b'BDFL', output)
Georg Brandlf9734072008-12-07 15:30:06 +0000120
121 def test_check_output_stdout_arg(self):
122 # check_output() function stderr redirected to stdout
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000123 with self.assertRaises(ValueError) as c:
Georg Brandlf9734072008-12-07 15:30:06 +0000124 output = subprocess.check_output(
125 [sys.executable, "-c", "print('will not be run')"],
126 stdout=sys.stdout)
Georg Brandlf9734072008-12-07 15:30:06 +0000127 self.fail("Expected ValueError when stdout arg supplied.")
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000128 self.assertIn('stdout', c.exception.args[0])
Georg Brandlf9734072008-12-07 15:30:06 +0000129
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000130 def test_call_kwargs(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000131 # call() function with keyword args
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000132 newenv = os.environ.copy()
133 newenv["FRUIT"] = "banana"
134 rc = subprocess.call([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000135 'import sys, os;'
136 'sys.exit(os.getenv("FRUIT")=="banana")'],
137 env=newenv)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000138 self.assertEqual(rc, 1)
139
Victor Stinner87b9bc32011-06-01 00:57:47 +0200140 def test_invalid_args(self):
141 # Popen() called with invalid arguments should raise TypeError
142 # but Popen.__del__ should not complain (issue #12085)
143 with support.captured_stderr() as s:
144 self.assertRaises(TypeError, subprocess.Popen, invalid_arg_name=1)
145 argcount = subprocess.Popen.__init__.__code__.co_argcount
146 too_many_args = [0] * (argcount + 1)
147 self.assertRaises(TypeError, subprocess.Popen, *too_many_args)
148 self.assertEqual(s.getvalue(), '')
149
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000150 def test_stdin_none(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000151 # .stdin is None when not redirected
Georg Brandl88fc6642007-02-09 21:28:07 +0000152 p = subprocess.Popen([sys.executable, "-c", 'print("banana")'],
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000153 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
Brian Curtin3c6a9512010-11-05 03:58:52 +0000154 self.addCleanup(p.stdout.close)
155 self.addCleanup(p.stderr.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000156 p.wait()
157 self.assertEqual(p.stdin, None)
158
159 def test_stdout_none(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000160 # .stdout is None when not redirected
Tim Peters29b6b4f2004-10-13 03:43:40 +0000161 p = subprocess.Popen([sys.executable, "-c",
Georg Brandl88fc6642007-02-09 21:28:07 +0000162 'print(" this bit of output is from a '
Tim Peters4052fe52004-10-13 03:29:54 +0000163 'test of stdout in a different '
Georg Brandl88fc6642007-02-09 21:28:07 +0000164 'process ...")'],
Tim Peters4052fe52004-10-13 03:29:54 +0000165 stdin=subprocess.PIPE, stderr=subprocess.PIPE)
Brian Curtin3c6a9512010-11-05 03:58:52 +0000166 self.addCleanup(p.stdin.close)
167 self.addCleanup(p.stderr.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000168 p.wait()
169 self.assertEqual(p.stdout, None)
170
171 def test_stderr_none(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000172 # .stderr is None when not redirected
Georg Brandl88fc6642007-02-09 21:28:07 +0000173 p = subprocess.Popen([sys.executable, "-c", 'print("banana")'],
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000174 stdin=subprocess.PIPE, stdout=subprocess.PIPE)
Brian Curtin3c6a9512010-11-05 03:58:52 +0000175 self.addCleanup(p.stdout.close)
176 self.addCleanup(p.stdin.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000177 p.wait()
178 self.assertEqual(p.stderr, None)
179
Chris Jerdonekec3ea942012-09-30 00:10:28 -0700180 # For use in the test_cwd* tests below.
181 def _normalize_cwd(self, cwd):
182 # Normalize an expected cwd (for Tru64 support).
183 # We can't use os.path.realpath since it doesn't expand Tru64 {memb}
184 # strings. See bug #1063571.
185 original_cwd = os.getcwd()
186 os.chdir(cwd)
187 cwd = os.getcwd()
188 os.chdir(original_cwd)
189 return cwd
190
191 # For use in the test_cwd* tests below.
192 def _split_python_path(self):
193 # Return normalized (python_dir, python_base).
194 python_path = os.path.realpath(sys.executable)
195 return os.path.split(python_path)
196
197 # For use in the test_cwd* tests below.
198 def _assert_cwd(self, expected_cwd, python_arg, **kwargs):
199 # Invoke Python via Popen, and assert that (1) the call succeeds,
200 # and that (2) the current working directory of the child process
201 # matches *expected_cwd*.
202 p = subprocess.Popen([python_arg, "-c",
203 "import os, sys; "
204 "sys.stdout.write(os.getcwd()); "
205 "sys.exit(47)"],
206 stdout=subprocess.PIPE,
207 **kwargs)
208 self.addCleanup(p.stdout.close)
Ezio Melotti184bdfb2010-02-18 09:37:05 +0000209 p.wait()
Chris Jerdonekec3ea942012-09-30 00:10:28 -0700210 self.assertEqual(47, p.returncode)
211 normcase = os.path.normcase
212 self.assertEqual(normcase(expected_cwd),
213 normcase(p.stdout.read().decode("utf-8")))
214
215 def test_cwd(self):
216 # Check that cwd changes the cwd for the child process.
217 temp_dir = tempfile.gettempdir()
218 temp_dir = self._normalize_cwd(temp_dir)
219 self._assert_cwd(temp_dir, sys.executable, cwd=temp_dir)
220
Chris Jerdonekc2cd6262012-09-30 09:45:00 -0700221 @unittest.skipIf(mswindows, "pending resolution of issue #15533")
Chris Jerdonekec3ea942012-09-30 00:10:28 -0700222 def test_cwd_with_relative_arg(self):
223 # Check that Popen looks for args[0] relative to cwd if args[0]
224 # is relative.
225 python_dir, python_base = self._split_python_path()
226 rel_python = os.path.join(os.curdir, python_base)
227 with support.temp_cwd() as wrong_dir:
228 # Before calling with the correct cwd, confirm that the call fails
229 # without cwd and with the wrong cwd.
230 self.assertRaises(OSError, subprocess.Popen,
231 [rel_python])
232 self.assertRaises(OSError, subprocess.Popen,
233 [rel_python], cwd=wrong_dir)
234 python_dir = self._normalize_cwd(python_dir)
235 self._assert_cwd(python_dir, rel_python, cwd=python_dir)
236
Chris Jerdonekc2cd6262012-09-30 09:45:00 -0700237 @unittest.skipIf(mswindows, "pending resolution of issue #15533")
Chris Jerdonekec3ea942012-09-30 00:10:28 -0700238 def test_cwd_with_relative_executable(self):
239 # Check that Popen looks for executable relative to cwd if executable
240 # is relative (and that executable takes precedence over args[0]).
241 python_dir, python_base = self._split_python_path()
242 rel_python = os.path.join(os.curdir, python_base)
243 doesntexist = "somethingyoudonthave"
244 with support.temp_cwd() as wrong_dir:
245 # Before calling with the correct cwd, confirm that the call fails
246 # without cwd and with the wrong cwd.
247 self.assertRaises(OSError, subprocess.Popen,
248 [doesntexist], executable=rel_python)
249 self.assertRaises(OSError, subprocess.Popen,
250 [doesntexist], executable=rel_python,
251 cwd=wrong_dir)
252 python_dir = self._normalize_cwd(python_dir)
253 self._assert_cwd(python_dir, doesntexist, executable=rel_python,
254 cwd=python_dir)
255
256 def test_cwd_with_absolute_arg(self):
257 # Check that Popen can find the executable when the cwd is wrong
258 # if args[0] is an absolute path.
259 python_dir, python_base = self._split_python_path()
260 abs_python = os.path.join(python_dir, python_base)
261 rel_python = os.path.join(os.curdir, python_base)
262 with script_helper.temp_dir() as wrong_dir:
263 # Before calling with an absolute path, confirm that using a
264 # relative path fails.
265 self.assertRaises(OSError, subprocess.Popen,
266 [rel_python], cwd=wrong_dir)
267 wrong_dir = self._normalize_cwd(wrong_dir)
268 self._assert_cwd(wrong_dir, abs_python, cwd=wrong_dir)
269
270 def test_executable_with_cwd(self):
271 python_dir, python_base = self._split_python_path()
272 python_dir = self._normalize_cwd(python_dir)
273 self._assert_cwd(python_dir, "somethingyoudonthave",
274 executable=sys.executable, cwd=python_dir)
Ezio Melotti184bdfb2010-02-18 09:37:05 +0000275
276 @unittest.skipIf(sysconfig.is_python_build(),
277 "need an installed Python. See #7774")
278 def test_executable_without_cwd(self):
279 # For a normal installation, it should work without 'cwd'
280 # argument. For test runs in the build directory, see #7774.
Chris Jerdonekec3ea942012-09-30 00:10:28 -0700281 self._assert_cwd('', "somethingyoudonthave", executable=sys.executable)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000282
283 def test_stdin_pipe(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000284 # stdin redirection
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000285 p = subprocess.Popen([sys.executable, "-c",
286 'import sys; sys.exit(sys.stdin.read() == "pear")'],
287 stdin=subprocess.PIPE)
Guido van Rossumbb839ef2007-08-27 23:58:21 +0000288 p.stdin.write(b"pear")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000289 p.stdin.close()
290 p.wait()
291 self.assertEqual(p.returncode, 1)
292
293 def test_stdin_filedes(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000294 # stdin is set to open file descriptor
Tim Peterse718f612004-10-12 21:51:32 +0000295 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000296 self.addCleanup(tf.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000297 d = tf.fileno()
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000298 os.write(d, b"pear")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000299 os.lseek(d, 0, 0)
300 p = subprocess.Popen([sys.executable, "-c",
301 'import sys; sys.exit(sys.stdin.read() == "pear")'],
302 stdin=d)
303 p.wait()
304 self.assertEqual(p.returncode, 1)
305
306 def test_stdin_fileobj(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000307 # stdin is set to open file object
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000308 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000309 self.addCleanup(tf.close)
Guido van Rossumbb839ef2007-08-27 23:58:21 +0000310 tf.write(b"pear")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000311 tf.seek(0)
312 p = subprocess.Popen([sys.executable, "-c",
313 'import sys; sys.exit(sys.stdin.read() == "pear")'],
314 stdin=tf)
315 p.wait()
316 self.assertEqual(p.returncode, 1)
317
318 def test_stdout_pipe(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000319 # stdout redirection
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000320 p = subprocess.Popen([sys.executable, "-c",
321 'import sys; sys.stdout.write("orange")'],
322 stdout=subprocess.PIPE)
Brian Curtin3c6a9512010-11-05 03:58:52 +0000323 self.addCleanup(p.stdout.close)
Guido van Rossumfa0054a2007-05-24 04:05:35 +0000324 self.assertEqual(p.stdout.read(), b"orange")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000325
326 def test_stdout_filedes(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000327 # stdout is set to open file descriptor
Tim Peterse718f612004-10-12 21:51:32 +0000328 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000329 self.addCleanup(tf.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000330 d = tf.fileno()
331 p = subprocess.Popen([sys.executable, "-c",
332 'import sys; sys.stdout.write("orange")'],
333 stdout=d)
334 p.wait()
335 os.lseek(d, 0, 0)
Guido van Rossumc9e363c2007-05-15 23:18:55 +0000336 self.assertEqual(os.read(d, 1024), b"orange")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000337
338 def test_stdout_fileobj(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000339 # stdout is set to open file object
Tim Peterse718f612004-10-12 21:51:32 +0000340 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000341 self.addCleanup(tf.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000342 p = subprocess.Popen([sys.executable, "-c",
343 'import sys; sys.stdout.write("orange")'],
344 stdout=tf)
345 p.wait()
346 tf.seek(0)
Guido van Rossumfa0054a2007-05-24 04:05:35 +0000347 self.assertEqual(tf.read(), b"orange")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000348
349 def test_stderr_pipe(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000350 # stderr redirection
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000351 p = subprocess.Popen([sys.executable, "-c",
352 'import sys; sys.stderr.write("strawberry")'],
353 stderr=subprocess.PIPE)
Brian Curtin3c6a9512010-11-05 03:58:52 +0000354 self.addCleanup(p.stderr.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000355 self.assertStderrEqual(p.stderr.read(), b"strawberry")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000356
357 def test_stderr_filedes(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000358 # stderr is set to open file descriptor
Tim Peterse718f612004-10-12 21:51:32 +0000359 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000360 self.addCleanup(tf.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000361 d = tf.fileno()
362 p = subprocess.Popen([sys.executable, "-c",
363 'import sys; sys.stderr.write("strawberry")'],
364 stderr=d)
365 p.wait()
366 os.lseek(d, 0, 0)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000367 self.assertStderrEqual(os.read(d, 1024), b"strawberry")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000368
369 def test_stderr_fileobj(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000370 # stderr is set to open file object
Tim Peterse718f612004-10-12 21:51:32 +0000371 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000372 self.addCleanup(tf.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000373 p = subprocess.Popen([sys.executable, "-c",
374 'import sys; sys.stderr.write("strawberry")'],
375 stderr=tf)
376 p.wait()
377 tf.seek(0)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000378 self.assertStderrEqual(tf.read(), b"strawberry")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000379
380 def test_stdout_stderr_pipe(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000381 # capture stdout and stderr to the same pipe
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000382 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000383 'import sys;'
384 'sys.stdout.write("apple");'
385 'sys.stdout.flush();'
386 'sys.stderr.write("orange")'],
387 stdout=subprocess.PIPE,
388 stderr=subprocess.STDOUT)
Brian Curtin3c6a9512010-11-05 03:58:52 +0000389 self.addCleanup(p.stdout.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000390 self.assertStderrEqual(p.stdout.read(), b"appleorange")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000391
392 def test_stdout_stderr_file(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000393 # capture stdout and stderr to the same open file
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000394 tf = tempfile.TemporaryFile()
Benjamin Petersoncc221b22010-10-31 02:06:21 +0000395 self.addCleanup(tf.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000396 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000397 'import sys;'
398 'sys.stdout.write("apple");'
399 'sys.stdout.flush();'
400 'sys.stderr.write("orange")'],
401 stdout=tf,
402 stderr=tf)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000403 p.wait()
404 tf.seek(0)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000405 self.assertStderrEqual(tf.read(), b"appleorange")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000406
Thomas Wouters89f507f2006-12-13 04:49:30 +0000407 def test_stdout_filedes_of_stdout(self):
408 # stdout is set to 1 (#1531862).
Antoine Pitrou9cadb1b2008-09-15 23:02:56 +0000409 cmd = r"import sys, os; sys.exit(os.write(sys.stdout.fileno(), b'.\n'))"
Thomas Wouters89f507f2006-12-13 04:49:30 +0000410 rc = subprocess.call([sys.executable, "-c", cmd], stdout=1)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000411 self.assertEqual(rc, 2)
Thomas Wouters89f507f2006-12-13 04:49:30 +0000412
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000413 def test_env(self):
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000414 newenv = os.environ.copy()
415 newenv["FRUIT"] = "orange"
Victor Stinnerf1512a22011-06-21 17:18:38 +0200416 with subprocess.Popen([sys.executable, "-c",
417 'import sys,os;'
418 'sys.stdout.write(os.getenv("FRUIT"))'],
419 stdout=subprocess.PIPE,
420 env=newenv) as p:
421 stdout, stderr = p.communicate()
422 self.assertEqual(stdout, b"orange")
423
Victor Stinner62d51182011-06-23 01:02:25 +0200424 # Windows requires at least the SYSTEMROOT environment variable to start
425 # Python
426 @unittest.skipIf(sys.platform == 'win32',
427 'cannot test an empty env on Windows')
Victor Stinner237e5cb2011-06-22 21:28:43 +0200428 @unittest.skipIf(sysconfig.get_config_var('Py_ENABLE_SHARED') is not None,
Victor Stinner372309a2011-06-21 21:59:06 +0200429 'the python library cannot be loaded '
430 'with an empty environment')
Victor Stinnerf1512a22011-06-21 17:18:38 +0200431 def test_empty_env(self):
432 with subprocess.Popen([sys.executable, "-c",
433 'import os; '
Victor Stinner372309a2011-06-21 21:59:06 +0200434 'print(list(os.environ.keys()))'],
Victor Stinnerf1512a22011-06-21 17:18:38 +0200435 stdout=subprocess.PIPE,
436 env={}) as p:
437 stdout, stderr = p.communicate()
Victor Stinner237e5cb2011-06-22 21:28:43 +0200438 self.assertIn(stdout.strip(),
439 (b"[]",
440 # Mac OS X adds __CF_USER_TEXT_ENCODING variable to an empty
441 # environment
442 b"['__CF_USER_TEXT_ENCODING']"))
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000443
Peter Astrandcbac93c2005-03-03 20:24:28 +0000444 def test_communicate_stdin(self):
445 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000446 'import sys;'
447 'sys.exit(sys.stdin.read() == "pear")'],
Peter Astrandcbac93c2005-03-03 20:24:28 +0000448 stdin=subprocess.PIPE)
Guido van Rossumbb839ef2007-08-27 23:58:21 +0000449 p.communicate(b"pear")
Peter Astrandcbac93c2005-03-03 20:24:28 +0000450 self.assertEqual(p.returncode, 1)
451
452 def test_communicate_stdout(self):
453 p = subprocess.Popen([sys.executable, "-c",
454 'import sys; sys.stdout.write("pineapple")'],
455 stdout=subprocess.PIPE)
456 (stdout, stderr) = p.communicate()
Guido van Rossumfa0054a2007-05-24 04:05:35 +0000457 self.assertEqual(stdout, b"pineapple")
Peter Astrandcbac93c2005-03-03 20:24:28 +0000458 self.assertEqual(stderr, None)
459
460 def test_communicate_stderr(self):
461 p = subprocess.Popen([sys.executable, "-c",
462 'import sys; sys.stderr.write("pineapple")'],
463 stderr=subprocess.PIPE)
464 (stdout, stderr) = p.communicate()
465 self.assertEqual(stdout, None)
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000466 self.assertStderrEqual(stderr, b"pineapple")
Peter Astrandcbac93c2005-03-03 20:24:28 +0000467
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000468 def test_communicate(self):
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000469 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000470 'import sys,os;'
471 'sys.stderr.write("pineapple");'
472 'sys.stdout.write(sys.stdin.read())'],
473 stdin=subprocess.PIPE,
474 stdout=subprocess.PIPE,
475 stderr=subprocess.PIPE)
Brian Curtin19a53792010-11-05 17:09:05 +0000476 self.addCleanup(p.stdout.close)
477 self.addCleanup(p.stderr.close)
478 self.addCleanup(p.stdin.close)
Georg Brandl1abcbf82008-07-01 19:28:43 +0000479 (stdout, stderr) = p.communicate(b"banana")
Guido van Rossumc9e363c2007-05-15 23:18:55 +0000480 self.assertEqual(stdout, b"banana")
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000481 self.assertStderrEqual(stderr, b"pineapple")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000482
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000483 # Test for the fd leak reported in http://bugs.python.org/issue2791.
484 def test_communicate_pipe_fd_leak(self):
Victor Stinner667d4b52010-12-25 22:40:32 +0000485 for stdin_pipe in (False, True):
486 for stdout_pipe in (False, True):
487 for stderr_pipe in (False, True):
488 options = {}
489 if stdin_pipe:
490 options['stdin'] = subprocess.PIPE
491 if stdout_pipe:
492 options['stdout'] = subprocess.PIPE
493 if stderr_pipe:
494 options['stderr'] = subprocess.PIPE
495 if not options:
496 continue
497 p = subprocess.Popen((sys.executable, "-c", "pass"), **options)
498 p.communicate()
499 if p.stdin is not None:
500 self.assertTrue(p.stdin.closed)
501 if p.stdout is not None:
502 self.assertTrue(p.stdout.closed)
503 if p.stderr is not None:
504 self.assertTrue(p.stderr.closed)
Georg Brandlf08a9dd2008-06-10 16:57:31 +0000505
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000506 def test_communicate_returns(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000507 # communicate() should return None if no redirection is active
Tim Peters3b01a702004-10-12 22:19:32 +0000508 p = subprocess.Popen([sys.executable, "-c",
509 "import sys; sys.exit(47)"])
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000510 (stdout, stderr) = p.communicate()
511 self.assertEqual(stdout, None)
512 self.assertEqual(stderr, None)
513
514 def test_communicate_pipe_buf(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000515 # communicate() with writes larger than pipe_buf
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000516 # This test will probably deadlock rather than fail, if
Tim Peterse718f612004-10-12 21:51:32 +0000517 # communicate() does not work properly.
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000518 x, y = os.pipe()
519 if mswindows:
520 pipe_buf = 512
521 else:
522 pipe_buf = os.fpathconf(x, "PC_PIPE_BUF")
523 os.close(x)
524 os.close(y)
525 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000526 'import sys,os;'
527 'sys.stdout.write(sys.stdin.read(47));'
528 'sys.stderr.write("xyz"*%d);'
529 'sys.stdout.write(sys.stdin.read())' % pipe_buf],
530 stdin=subprocess.PIPE,
531 stdout=subprocess.PIPE,
532 stderr=subprocess.PIPE)
Brian Curtin19a53792010-11-05 17:09:05 +0000533 self.addCleanup(p.stdout.close)
534 self.addCleanup(p.stderr.close)
535 self.addCleanup(p.stdin.close)
Guido van Rossumc9e363c2007-05-15 23:18:55 +0000536 string_to_write = b"abc"*pipe_buf
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000537 (stdout, stderr) = p.communicate(string_to_write)
538 self.assertEqual(stdout, string_to_write)
539
540 def test_writes_before_communicate(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000541 # stdin.write before communicate()
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000542 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000543 'import sys,os;'
544 'sys.stdout.write(sys.stdin.read())'],
545 stdin=subprocess.PIPE,
546 stdout=subprocess.PIPE,
547 stderr=subprocess.PIPE)
Brian Curtin19a53792010-11-05 17:09:05 +0000548 self.addCleanup(p.stdout.close)
549 self.addCleanup(p.stderr.close)
550 self.addCleanup(p.stdin.close)
Guido van Rossumbb839ef2007-08-27 23:58:21 +0000551 p.stdin.write(b"banana")
552 (stdout, stderr) = p.communicate(b"split")
Guido van Rossumc9e363c2007-05-15 23:18:55 +0000553 self.assertEqual(stdout, b"bananasplit")
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000554 self.assertStderrEqual(stderr, b"")
Tim Peterse718f612004-10-12 21:51:32 +0000555
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000556 def test_universal_newlines(self):
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000557 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000558 'import sys,os;' + SETBINARY +
Antoine Pitrouec2d2692012-08-05 00:23:40 +0200559 'buf = sys.stdout.buffer;'
560 'buf.write(sys.stdin.readline().encode());'
561 'buf.flush();'
562 'buf.write(b"line2\\n");'
563 'buf.flush();'
564 'buf.write(sys.stdin.read().encode());'
565 'buf.flush();'
566 'buf.write(b"line4\\n");'
567 'buf.flush();'
568 'buf.write(b"line5\\r\\n");'
569 'buf.flush();'
570 'buf.write(b"line6\\r");'
571 'buf.flush();'
572 'buf.write(b"\\nline7");'
573 'buf.flush();'
574 'buf.write(b"\\nline8");'],
Antoine Pitrouab85ff32011-07-23 22:03:45 +0200575 stdin=subprocess.PIPE,
Guido van Rossum98297ee2007-11-06 21:34:58 +0000576 stdout=subprocess.PIPE,
577 universal_newlines=1)
Antoine Pitrouab85ff32011-07-23 22:03:45 +0200578 p.stdin.write("line1\n")
579 self.assertEqual(p.stdout.readline(), "line1\n")
580 p.stdin.write("line3\n")
581 p.stdin.close()
Brian Curtin3c6a9512010-11-05 03:58:52 +0000582 self.addCleanup(p.stdout.close)
Antoine Pitrouab85ff32011-07-23 22:03:45 +0200583 self.assertEqual(p.stdout.readline(),
584 "line2\n")
585 self.assertEqual(p.stdout.read(6),
586 "line3\n")
587 self.assertEqual(p.stdout.read(),
588 "line4\nline5\nline6\nline7\nline8")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000589
590 def test_universal_newlines_communicate(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000591 # universal newlines through communicate()
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000592 p = subprocess.Popen([sys.executable, "-c",
Guido van Rossum98297ee2007-11-06 21:34:58 +0000593 'import sys,os;' + SETBINARY +
Antoine Pitrouec2d2692012-08-05 00:23:40 +0200594 'buf = sys.stdout.buffer;'
595 'buf.write(b"line2\\n");'
596 'buf.flush();'
597 'buf.write(b"line4\\n");'
598 'buf.flush();'
599 'buf.write(b"line5\\r\\n");'
600 'buf.flush();'
601 'buf.write(b"line6\\r");'
602 'buf.flush();'
603 'buf.write(b"\\nline7");'
604 'buf.flush();'
605 'buf.write(b"\\nline8");'],
Antoine Pitrouab85ff32011-07-23 22:03:45 +0200606 stderr=subprocess.PIPE,
607 stdout=subprocess.PIPE,
Guido van Rossum98297ee2007-11-06 21:34:58 +0000608 universal_newlines=1)
Brian Curtin19a53792010-11-05 17:09:05 +0000609 self.addCleanup(p.stdout.close)
610 self.addCleanup(p.stderr.close)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000611 (stdout, stderr) = p.communicate()
Antoine Pitrouab85ff32011-07-23 22:03:45 +0200612 self.assertEqual(stdout,
613 "line2\nline4\nline5\nline6\nline7\nline8")
614
615 def test_universal_newlines_communicate_stdin(self):
616 # universal newlines through communicate(), with only stdin
617 p = subprocess.Popen([sys.executable, "-c",
618 'import sys,os;' + SETBINARY + '''\nif True:
619 s = sys.stdin.readline()
620 assert s == "line1\\n", repr(s)
621 s = sys.stdin.read()
622 assert s == "line3\\n", repr(s)
623 '''],
624 stdin=subprocess.PIPE,
625 universal_newlines=1)
626 (stdout, stderr) = p.communicate("line1\nline3\n")
627 self.assertEqual(p.returncode, 0)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000628
Andrew Svetlovf3765072012-08-14 18:35:17 +0300629 def test_universal_newlines_communicate_input_none(self):
630 # Test communicate(input=None) with universal newlines.
631 #
632 # We set stdout to PIPE because, as of this writing, a different
633 # code path is tested when the number of pipes is zero or one.
634 p = subprocess.Popen([sys.executable, "-c", "pass"],
635 stdin=subprocess.PIPE,
636 stdout=subprocess.PIPE,
637 universal_newlines=True)
638 p.communicate()
639 self.assertEqual(p.returncode, 0)
640
Serhiy Storchakab3f194d2013-02-04 16:47:39 +0200641 def test_universal_newlines_communicate_stdin_stdout_stderr(self):
642 # universal newlines through communicate(), with stdin, stdout, stderr
643 p = subprocess.Popen([sys.executable, "-c",
644 'import sys,os;' + SETBINARY + '''\nif True:
645 s = sys.stdin.buffer.readline()
646 sys.stdout.buffer.write(s)
647 sys.stdout.buffer.write(b"line2\\r")
648 sys.stderr.buffer.write(b"eline2\\n")
649 s = sys.stdin.buffer.read()
650 sys.stdout.buffer.write(s)
651 sys.stdout.buffer.write(b"line4\\n")
652 sys.stdout.buffer.write(b"line5\\r\\n")
653 sys.stderr.buffer.write(b"eline6\\r")
654 sys.stderr.buffer.write(b"eline7\\r\\nz")
655 '''],
656 stdin=subprocess.PIPE,
657 stderr=subprocess.PIPE,
658 stdout=subprocess.PIPE,
659 universal_newlines=True)
660 self.addCleanup(p.stdout.close)
661 self.addCleanup(p.stderr.close)
662 (stdout, stderr) = p.communicate("line1\nline3\n")
663 self.assertEqual(p.returncode, 0)
664 self.assertEqual("line1\nline2\nline3\nline4\nline5\n", stdout)
665 # Python debug build push something like "[42442 refs]\n"
666 # to stderr at exit of subprocess.
667 # Don't use assertStderrEqual because it strips CR and LF from output.
668 self.assertTrue(stderr.startswith("eline2\neline6\neline7\n"))
669
Andrew Svetlov82860712012-08-19 22:13:41 +0300670 def test_universal_newlines_communicate_encodings(self):
671 # Check that universal newlines mode works for various encodings,
672 # in particular for encodings in the UTF-16 and UTF-32 families.
673 # See issue #15595.
674 #
675 # UTF-16 and UTF-32-BE are sufficient to check both with BOM and
676 # without, and UTF-16 and UTF-32.
677 for encoding in ['utf-16', 'utf-32-be']:
678 old_getpreferredencoding = locale.getpreferredencoding
679 # Indirectly via io.TextIOWrapper, Popen() defaults to
680 # locale.getpreferredencoding(False) and earlier in Python 3.2 to
681 # locale.getpreferredencoding().
682 def getpreferredencoding(do_setlocale=True):
683 return encoding
684 code = ("import sys; "
685 r"sys.stdout.buffer.write('1\r\n2\r3\n4'.encode('%s'))" %
686 encoding)
687 args = [sys.executable, '-c', code]
688 try:
689 locale.getpreferredencoding = getpreferredencoding
690 # We set stdin to be non-None because, as of this writing,
691 # a different code path is used when the number of pipes is
692 # zero or one.
693 popen = subprocess.Popen(args, universal_newlines=True,
694 stdin=subprocess.PIPE,
695 stdout=subprocess.PIPE)
696 stdout, stderr = popen.communicate(input='')
697 finally:
698 locale.getpreferredencoding = old_getpreferredencoding
699
700 self.assertEqual(stdout, '1\n2\n3\n4')
701
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000702 def test_no_leaking(self):
Tim Peters7b759da2004-10-12 22:29:54 +0000703 # Make sure we leak no resources
Antoine Pitrou8db30272010-09-18 22:38:48 +0000704 if not mswindows:
Peter Astrandf7f1bb72005-03-03 20:47:37 +0000705 max_handles = 1026 # too much for most UNIX systems
706 else:
Antoine Pitrou8db30272010-09-18 22:38:48 +0000707 max_handles = 2050 # too much for (at least some) Windows setups
708 handles = []
Gregory P. Smith81ce6852011-03-15 02:04:11 -0400709 tmpdir = tempfile.mkdtemp()
Antoine Pitrou8db30272010-09-18 22:38:48 +0000710 try:
711 for i in range(max_handles):
712 try:
Gregory P. Smith81ce6852011-03-15 02:04:11 -0400713 tmpfile = os.path.join(tmpdir, support.TESTFN)
714 handles.append(os.open(tmpfile, os.O_WRONLY|os.O_CREAT))
Antoine Pitrou8db30272010-09-18 22:38:48 +0000715 except OSError as e:
716 if e.errno != errno.EMFILE:
717 raise
718 break
719 else:
720 self.skipTest("failed to reach the file descriptor limit "
721 "(tried %d)" % max_handles)
722 # Close a couple of them (should be enough for a subprocess)
723 for i in range(10):
724 os.close(handles.pop())
725 # Loop creating some subprocesses. If one of them leaks some fds,
726 # the next loop iteration will fail by reaching the max fd limit.
727 for i in range(15):
728 p = subprocess.Popen([sys.executable, "-c",
729 "import sys;"
730 "sys.stdout.write(sys.stdin.read())"],
731 stdin=subprocess.PIPE,
732 stdout=subprocess.PIPE,
733 stderr=subprocess.PIPE)
734 data = p.communicate(b"lime")[0]
735 self.assertEqual(data, b"lime")
736 finally:
737 for h in handles:
738 os.close(h)
Gregory P. Smith81ce6852011-03-15 02:04:11 -0400739 shutil.rmtree(tmpdir)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000740
741 def test_list2cmdline(self):
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000742 self.assertEqual(subprocess.list2cmdline(['a b c', 'd', 'e']),
743 '"a b c" d e')
744 self.assertEqual(subprocess.list2cmdline(['ab"c', '\\', 'd']),
745 'ab\\"c \\ d')
Christian Heimesfdab48e2008-01-20 09:06:41 +0000746 self.assertEqual(subprocess.list2cmdline(['ab"c', ' \\', 'd']),
747 'ab\\"c " \\\\" d')
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000748 self.assertEqual(subprocess.list2cmdline(['a\\\\\\b', 'de fg', 'h']),
749 'a\\\\\\b "de fg" h')
750 self.assertEqual(subprocess.list2cmdline(['a\\"b', 'c', 'd']),
751 'a\\\\\\"b c d')
752 self.assertEqual(subprocess.list2cmdline(['a\\\\b c', 'd', 'e']),
753 '"a\\\\b c" d e')
754 self.assertEqual(subprocess.list2cmdline(['a\\\\b\\ c', 'd', 'e']),
755 '"a\\\\b\\ c" d e')
Thomas Woutersfc7bb8c2007-01-15 15:49:28 +0000756 self.assertEqual(subprocess.list2cmdline(['ab', '']),
757 'ab ""')
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000758
759
760 def test_poll(self):
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000761 p = subprocess.Popen([sys.executable,
Tim Peters29b6b4f2004-10-13 03:43:40 +0000762 "-c", "import time; time.sleep(1)"])
763 count = 0
764 while p.poll() is None:
765 time.sleep(0.1)
766 count += 1
767 # We expect that the poll loop probably went around about 10 times,
768 # but, based on system scheduling we can't control, it's possible
769 # poll() never returned None. It "should be" very rare that it
770 # didn't go around at least twice.
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000771 self.assertGreaterEqual(count, 2)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000772 # Subsequent invocations should just return the returncode
773 self.assertEqual(p.poll(), 0)
774
775
776 def test_wait(self):
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000777 p = subprocess.Popen([sys.executable,
778 "-c", "import time; time.sleep(2)"])
779 self.assertEqual(p.wait(), 0)
780 # Subsequent invocations should just return the returncode
781 self.assertEqual(p.wait(), 0)
Tim Peterse718f612004-10-12 21:51:32 +0000782
Peter Astrand738131d2004-11-30 21:04:45 +0000783
784 def test_invalid_bufsize(self):
785 # an invalid type of the bufsize argument should raise
786 # TypeError.
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000787 with self.assertRaises(TypeError):
Peter Astrand738131d2004-11-30 21:04:45 +0000788 subprocess.Popen([sys.executable, "-c", "pass"], "orange")
Peter Astrand738131d2004-11-30 21:04:45 +0000789
Guido van Rossum46a05a72007-06-07 21:56:45 +0000790 def test_bufsize_is_none(self):
791 # bufsize=None should be the same as bufsize=0.
792 p = subprocess.Popen([sys.executable, "-c", "pass"], None)
793 self.assertEqual(p.wait(), 0)
794 # Again with keyword arg
795 p = subprocess.Popen([sys.executable, "-c", "pass"], bufsize=None)
796 self.assertEqual(p.wait(), 0)
797
Benjamin Petersond75fcb42009-02-19 04:22:03 +0000798 def test_leaking_fds_on_error(self):
799 # see bug #5179: Popen leaks file descriptors to PIPEs if
800 # the child fails to execute; this will eventually exhaust
801 # the maximum number of open fds. 1024 seems a very common
802 # value for that limit, but Windows has 2048, so we loop
803 # 1024 times (each call leaked two fds).
804 for i in range(1024):
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000805 # Windows raises IOError. Others raise OSError.
806 with self.assertRaises(EnvironmentError) as c:
Benjamin Petersond75fcb42009-02-19 04:22:03 +0000807 subprocess.Popen(['nonexisting_i_hope'],
808 stdout=subprocess.PIPE,
809 stderr=subprocess.PIPE)
R David Murray384069c2011-03-13 22:26:53 -0400810 # ignore errors that indicate the command was not found
R David Murray6924bd72011-03-13 22:48:55 -0400811 if c.exception.errno not in (errno.ENOENT, errno.EACCES):
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000812 raise c.exception
Benjamin Petersond75fcb42009-02-19 04:22:03 +0000813
Victor Stinnerb3693582010-05-21 20:13:12 +0000814 def test_issue8780(self):
815 # Ensure that stdout is inherited from the parent
816 # if stdout=PIPE is not used
817 code = ';'.join((
818 'import subprocess, sys',
819 'retcode = subprocess.call('
820 "[sys.executable, '-c', 'print(\"Hello World!\")'])",
821 'assert retcode == 0'))
822 output = subprocess.check_output([sys.executable, '-c', code])
Ezio Melottib3aedd42010-11-20 19:04:17 +0000823 self.assertTrue(output.startswith(b'Hello World!'), ascii(output))
Victor Stinnerb3693582010-05-21 20:13:12 +0000824
Tim Goldenaf5ac392010-08-06 13:03:56 +0000825 def test_handles_closed_on_exception(self):
826 # If CreateProcess exits with an error, ensure the
827 # duplicate output handles are released
828 ifhandle, ifname = mkstemp()
829 ofhandle, ofname = mkstemp()
830 efhandle, efname = mkstemp()
831 try:
832 subprocess.Popen (["*"], stdin=ifhandle, stdout=ofhandle,
833 stderr=efhandle)
834 except OSError:
835 os.close(ifhandle)
836 os.remove(ifname)
837 os.close(ofhandle)
838 os.remove(ofname)
839 os.close(efhandle)
840 os.remove(efname)
841 self.assertFalse(os.path.exists(ifname))
842 self.assertFalse(os.path.exists(ofname))
843 self.assertFalse(os.path.exists(efname))
844
Ross Lagerwall4f61b022011-04-05 15:34:00 +0200845 def test_communicate_epipe(self):
846 # Issue 10963: communicate() should hide EPIPE
847 p = subprocess.Popen([sys.executable, "-c", 'pass'],
848 stdin=subprocess.PIPE,
849 stdout=subprocess.PIPE,
850 stderr=subprocess.PIPE)
851 self.addCleanup(p.stdout.close)
852 self.addCleanup(p.stderr.close)
853 self.addCleanup(p.stdin.close)
854 p.communicate(b"x" * 2**20)
855
856 def test_communicate_epipe_only_stdin(self):
857 # Issue 10963: communicate() should hide EPIPE
858 p = subprocess.Popen([sys.executable, "-c", 'pass'],
859 stdin=subprocess.PIPE)
860 self.addCleanup(p.stdin.close)
861 time.sleep(2)
862 p.communicate(b"x" * 2**20)
863
Victor Stinner1848db82011-07-05 14:49:46 +0200864 @unittest.skipUnless(hasattr(signal, 'SIGALRM'),
865 "Requires signal.SIGALRM")
Victor Stinner2cfb6f32011-07-05 14:00:56 +0200866 def test_communicate_eintr(self):
867 # Issue #12493: communicate() should handle EINTR
868 def handler(signum, frame):
869 pass
870 old_handler = signal.signal(signal.SIGALRM, handler)
871 self.addCleanup(signal.signal, signal.SIGALRM, old_handler)
872
873 # the process is running for 2 seconds
874 args = [sys.executable, "-c", 'import time; time.sleep(2)']
875 for stream in ('stdout', 'stderr'):
876 kw = {stream: subprocess.PIPE}
877 with subprocess.Popen(args, **kw) as process:
878 signal.alarm(1)
879 # communicate() will be interrupted by SIGALRM
880 process.communicate()
881
Tim Peterse718f612004-10-12 21:51:32 +0000882
Gregory P. Smith3d8e7762012-11-10 22:32:22 -0800883 # This test is Linux-ish specific for simplicity to at least have
884 # some coverage. It is not a platform specific bug.
885 @unittest.skipUnless(os.path.isdir('/proc/%d/fd' % os.getpid()),
886 "Linux specific")
887 def test_failed_child_execute_fd_leak(self):
888 """Test for the fork() failure fd leak reported in issue16327."""
889 fd_directory = '/proc/%d/fd' % os.getpid()
890 fds_before_popen = os.listdir(fd_directory)
891 with self.assertRaises(PopenTestException):
892 PopenExecuteChildRaises(
893 [sys.executable, '-c', 'pass'], stdin=subprocess.PIPE,
894 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
895
896 # NOTE: This test doesn't verify that the real _execute_child
897 # does not close the file descriptors itself on the way out
898 # during an exception. Code inspection has confirmed that.
899
900 fds_after_exception = os.listdir(fd_directory)
901 self.assertEqual(fds_before_popen, fds_after_exception)
902
903
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000904# context manager
905class _SuppressCoreFiles(object):
906 """Try to prevent core files from being created."""
907 old_limit = None
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000908
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000909 def __enter__(self):
910 """Try to save previous ulimit, then set it to (0, 0)."""
Benjamin Peterson964561b2011-12-10 12:31:42 -0500911 if resource is not None:
912 try:
913 self.old_limit = resource.getrlimit(resource.RLIMIT_CORE)
914 resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
915 except (ValueError, resource.error):
916 pass
Thomas Wouters0e3f5912006-08-11 14:57:12 +0000917
Ronald Oussoren102d11a2010-07-23 09:50:05 +0000918 if sys.platform == 'darwin':
919 # Check if the 'Crash Reporter' on OSX was configured
920 # in 'Developer' mode and warn that it will get triggered
921 # when it is.
922 #
923 # This assumes that this context manager is used in tests
924 # that might trigger the next manager.
925 value = subprocess.Popen(['/usr/bin/defaults', 'read',
926 'com.apple.CrashReporter', 'DialogType'],
927 stdout=subprocess.PIPE).communicate()[0]
928 if value.strip() == b'developer':
929 print("this tests triggers the Crash Reporter, "
930 "that is intentional", end='')
931 sys.stdout.flush()
932
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000933 def __exit__(self, *args):
934 """Return core file behavior to default."""
935 if self.old_limit is None:
936 return
Benjamin Peterson964561b2011-12-10 12:31:42 -0500937 if resource is not None:
938 try:
939 resource.setrlimit(resource.RLIMIT_CORE, self.old_limit)
940 except (ValueError, resource.error):
941 pass
Fredrik Lundh5b3687d2004-10-12 15:26:28 +0000942
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000943
Florent Xiclunaf0cbd822010-03-04 21:50:56 +0000944@unittest.skipIf(mswindows, "POSIX specific tests")
Florent Xiclunac049d872010-03-27 22:47:23 +0000945class POSIXProcessTestCase(BaseTestCase):
Florent Xiclunaf0cbd822010-03-04 21:50:56 +0000946
Gregory P. Smith5591b022012-10-10 03:34:47 -0700947 def setUp(self):
948 super().setUp()
949 self._nonexistent_dir = "/_this/pa.th/does/not/exist"
950
951 def _get_chdir_exception(self):
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000952 try:
Gregory P. Smith5591b022012-10-10 03:34:47 -0700953 os.chdir(self._nonexistent_dir)
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000954 except OSError as e:
955 # This avoids hard coding the errno value or the OS perror()
956 # string and instead capture the exception that we want to see
957 # below for comparison.
958 desired_exception = e
Gregory P. Smith5591b022012-10-10 03:34:47 -0700959 desired_exception.strerror += ': ' + repr(self._nonexistent_dir)
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000960 else:
961 self.fail("chdir to nonexistant directory %s succeeded." %
Gregory P. Smith5591b022012-10-10 03:34:47 -0700962 self._nonexistent_dir)
963 return desired_exception
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000964
Gregory P. Smith5591b022012-10-10 03:34:47 -0700965 def test_exception_cwd(self):
966 """Test error in the child raised in the parent for a bad cwd."""
967 desired_exception = self._get_chdir_exception()
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000968 try:
Florent Xiclunab1e94e82010-02-27 22:12:37 +0000969 p = subprocess.Popen([sys.executable, "-c", ""],
Gregory P. Smith5591b022012-10-10 03:34:47 -0700970 cwd=self._nonexistent_dir)
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +0000971 except OSError as e:
972 # Test that the child process chdir failure actually makes
973 # it up to the parent process as the correct exception.
974 self.assertEqual(desired_exception.errno, e.errno)
975 self.assertEqual(desired_exception.strerror, e.strerror)
976 else:
977 self.fail("Expected OSError: %s" % desired_exception)
978
Gregory P. Smith5591b022012-10-10 03:34:47 -0700979 def test_exception_bad_executable(self):
980 """Test error in the child raised in the parent for a bad executable."""
981 desired_exception = self._get_chdir_exception()
982 try:
983 p = subprocess.Popen([sys.executable, "-c", ""],
984 executable=self._nonexistent_dir)
985 except OSError as e:
986 # Test that the child process exec failure actually makes
987 # it up to the parent process as the correct exception.
988 self.assertEqual(desired_exception.errno, e.errno)
989 self.assertEqual(desired_exception.strerror, e.strerror)
990 else:
991 self.fail("Expected OSError: %s" % desired_exception)
992
993 def test_exception_bad_args_0(self):
994 """Test error in the child raised in the parent for a bad args[0]."""
995 desired_exception = self._get_chdir_exception()
996 try:
997 p = subprocess.Popen([self._nonexistent_dir, "-c", ""])
998 except OSError as e:
999 # Test that the child process exec failure actually makes
1000 # it up to the parent process as the correct exception.
1001 self.assertEqual(desired_exception.errno, e.errno)
1002 self.assertEqual(desired_exception.strerror, e.strerror)
1003 else:
1004 self.fail("Expected OSError: %s" % desired_exception)
1005
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001006 def test_restore_signals(self):
1007 # Code coverage for both values of restore_signals to make sure it
1008 # at least does not blow up.
1009 # A test for behavior would be complex. Contributions welcome.
1010 subprocess.call([sys.executable, "-c", ""], restore_signals=True)
1011 subprocess.call([sys.executable, "-c", ""], restore_signals=False)
1012
1013 def test_start_new_session(self):
1014 # For code coverage of calling setsid(). We don't care if we get an
1015 # EPERM error from it depending on the test execution environment, that
1016 # still indicates that it was called.
1017 try:
1018 output = subprocess.check_output(
1019 [sys.executable, "-c",
1020 "import os; print(os.getpgid(os.getpid()))"],
1021 start_new_session=True)
1022 except OSError as e:
1023 if e.errno != errno.EPERM:
1024 raise
1025 else:
1026 parent_pgid = os.getpgid(os.getpid())
1027 child_pgid = int(output)
1028 self.assertNotEqual(parent_pgid, child_pgid)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001029
1030 def test_run_abort(self):
1031 # returncode handles signal termination
1032 with _SuppressCoreFiles():
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001033 p = subprocess.Popen([sys.executable, "-c",
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001034 'import os; os.abort()'])
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001035 p.wait()
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001036 self.assertEqual(-p.returncode, signal.SIGABRT)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001037
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001038 def test_preexec(self):
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001039 # DISCLAIMER: Setting environment variables is *not* a good use
1040 # of a preexec_fn. This is merely a test.
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001041 p = subprocess.Popen([sys.executable, "-c",
1042 'import sys,os;'
1043 'sys.stdout.write(os.getenv("FRUIT"))'],
1044 stdout=subprocess.PIPE,
1045 preexec_fn=lambda: os.putenv("FRUIT", "apple"))
Brian Curtin3c6a9512010-11-05 03:58:52 +00001046 self.addCleanup(p.stdout.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001047 self.assertEqual(p.stdout.read(), b"apple")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001048
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001049 def test_preexec_exception(self):
1050 def raise_it():
1051 raise ValueError("What if two swallows carried a coconut?")
1052 try:
1053 p = subprocess.Popen([sys.executable, "-c", ""],
1054 preexec_fn=raise_it)
1055 except RuntimeError as e:
1056 self.assertTrue(
1057 subprocess._posixsubprocess,
1058 "Expected a ValueError from the preexec_fn")
1059 except ValueError as e:
1060 self.assertIn("coconut", e.args[0])
1061 else:
1062 self.fail("Exception raised by preexec_fn did not make it "
1063 "to the parent process.")
1064
Gregory P. Smithe27faac2012-11-11 09:59:27 -08001065 class _TestExecuteChildPopen(subprocess.Popen):
1066 """Used to test behavior at the end of _execute_child."""
1067 def __init__(self, testcase, *args, **kwargs):
1068 self._testcase = testcase
1069 subprocess.Popen.__init__(self, *args, **kwargs)
Gregory P. Smith12489d92012-11-11 01:37:02 -08001070
Gregory P. Smithe27faac2012-11-11 09:59:27 -08001071 def _execute_child(self, *args, **kwargs):
Gregory P. Smith12489d92012-11-11 01:37:02 -08001072 try:
Gregory P. Smithe27faac2012-11-11 09:59:27 -08001073 subprocess.Popen._execute_child(self, *args, **kwargs)
Gregory P. Smith12489d92012-11-11 01:37:02 -08001074 finally:
1075 # Open a bunch of file descriptors and verify that
1076 # none of them are the same as the ones the Popen
1077 # instance is using for stdin/stdout/stderr.
1078 devzero_fds = [os.open("/dev/zero", os.O_RDONLY)
1079 for _ in range(8)]
1080 try:
1081 for fd in devzero_fds:
Gregory P. Smithe27faac2012-11-11 09:59:27 -08001082 self._testcase.assertNotIn(
1083 fd, (self.stdin.fileno(), self.stdout.fileno(),
1084 self.stderr.fileno()),
Gregory P. Smith12489d92012-11-11 01:37:02 -08001085 msg="At least one fd was closed early.")
1086 finally:
1087 map(os.close, devzero_fds)
1088
Gregory P. Smithe27faac2012-11-11 09:59:27 -08001089 @unittest.skipIf(not os.path.exists("/dev/zero"), "/dev/zero required.")
1090 def test_preexec_errpipe_does_not_double_close_pipes(self):
1091 """Issue16140: Don't double close pipes on preexec error."""
1092
1093 def raise_it():
1094 raise RuntimeError("force the _execute_child() errpipe_data path.")
Gregory P. Smith12489d92012-11-11 01:37:02 -08001095
1096 with self.assertRaises(RuntimeError):
Gregory P. Smithe27faac2012-11-11 09:59:27 -08001097 self._TestExecuteChildPopen(
1098 self, [sys.executable, "-c", "pass"],
Gregory P. Smith12489d92012-11-11 01:37:02 -08001099 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1100 stderr=subprocess.PIPE, preexec_fn=raise_it)
1101
Gregory P. Smith32ec9da2010-03-19 16:53:08 +00001102 def test_preexec_gc_module_failure(self):
1103 # This tests the code that disables garbage collection if the child
1104 # process will execute any Python.
1105 def raise_runtime_error():
1106 raise RuntimeError("this shouldn't escape")
1107 enabled = gc.isenabled()
1108 orig_gc_disable = gc.disable
1109 orig_gc_isenabled = gc.isenabled
1110 try:
1111 gc.disable()
1112 self.assertFalse(gc.isenabled())
1113 subprocess.call([sys.executable, '-c', ''],
1114 preexec_fn=lambda: None)
1115 self.assertFalse(gc.isenabled(),
1116 "Popen enabled gc when it shouldn't.")
1117
1118 gc.enable()
1119 self.assertTrue(gc.isenabled())
1120 subprocess.call([sys.executable, '-c', ''],
1121 preexec_fn=lambda: None)
1122 self.assertTrue(gc.isenabled(), "Popen left gc disabled.")
1123
1124 gc.disable = raise_runtime_error
1125 self.assertRaises(RuntimeError, subprocess.Popen,
1126 [sys.executable, '-c', ''],
1127 preexec_fn=lambda: None)
1128
1129 del gc.isenabled # force an AttributeError
1130 self.assertRaises(AttributeError, subprocess.Popen,
1131 [sys.executable, '-c', ''],
1132 preexec_fn=lambda: None)
1133 finally:
1134 gc.disable = orig_gc_disable
1135 gc.isenabled = orig_gc_isenabled
1136 if not enabled:
1137 gc.disable()
1138
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001139 def test_args_string(self):
1140 # args is a string
1141 fd, fname = mkstemp()
1142 # reopen in text mode
Victor Stinnerf6782ac2010-10-16 23:46:43 +00001143 with open(fd, "w", errors="surrogateescape") as fobj:
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001144 fobj.write("#!/bin/sh\n")
1145 fobj.write("exec '%s' -c 'import sys; sys.exit(47)'\n" %
1146 sys.executable)
1147 os.chmod(fname, 0o700)
1148 p = subprocess.Popen(fname)
1149 p.wait()
1150 os.remove(fname)
1151 self.assertEqual(p.returncode, 47)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001152
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001153 def test_invalid_args(self):
1154 # invalid arguments should raise ValueError
1155 self.assertRaises(ValueError, subprocess.call,
1156 [sys.executable, "-c",
1157 "import sys; sys.exit(47)"],
1158 startupinfo=47)
1159 self.assertRaises(ValueError, subprocess.call,
1160 [sys.executable, "-c",
1161 "import sys; sys.exit(47)"],
1162 creationflags=47)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001163
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001164 def test_shell_sequence(self):
1165 # Run command through the shell (sequence)
1166 newenv = os.environ.copy()
1167 newenv["FRUIT"] = "apple"
1168 p = subprocess.Popen(["echo $FRUIT"], shell=1,
1169 stdout=subprocess.PIPE,
1170 env=newenv)
Brian Curtin3c6a9512010-11-05 03:58:52 +00001171 self.addCleanup(p.stdout.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001172 self.assertEqual(p.stdout.read().strip(b" \t\r\n\f"), b"apple")
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001173
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001174 def test_shell_string(self):
1175 # Run command through the shell (string)
1176 newenv = os.environ.copy()
1177 newenv["FRUIT"] = "apple"
1178 p = subprocess.Popen("echo $FRUIT", shell=1,
1179 stdout=subprocess.PIPE,
1180 env=newenv)
Brian Curtin3c6a9512010-11-05 03:58:52 +00001181 self.addCleanup(p.stdout.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001182 self.assertEqual(p.stdout.read().strip(b" \t\r\n\f"), b"apple")
Christian Heimesa342c012008-04-20 21:01:16 +00001183
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001184 def test_call_string(self):
1185 # call() function with string argument on UNIX
1186 fd, fname = mkstemp()
1187 # reopen in text mode
Victor Stinnerf6782ac2010-10-16 23:46:43 +00001188 with open(fd, "w", errors="surrogateescape") as fobj:
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001189 fobj.write("#!/bin/sh\n")
1190 fobj.write("exec '%s' -c 'import sys; sys.exit(47)'\n" %
1191 sys.executable)
1192 os.chmod(fname, 0o700)
1193 rc = subprocess.call(fname)
1194 os.remove(fname)
1195 self.assertEqual(rc, 47)
Christian Heimesa342c012008-04-20 21:01:16 +00001196
Stefan Krah9542cc62010-07-19 14:20:53 +00001197 def test_specific_shell(self):
1198 # Issue #9265: Incorrect name passed as arg[0].
1199 shells = []
1200 for prefix in ['/bin', '/usr/bin/', '/usr/local/bin']:
1201 for name in ['bash', 'ksh']:
1202 sh = os.path.join(prefix, name)
1203 if os.path.isfile(sh):
1204 shells.append(sh)
1205 if not shells: # Will probably work for any shell but csh.
1206 self.skipTest("bash or ksh required for this test")
1207 sh = '/bin/sh'
1208 if os.path.isfile(sh) and not os.path.islink(sh):
1209 # Test will fail if /bin/sh is a symlink to csh.
1210 shells.append(sh)
1211 for sh in shells:
1212 p = subprocess.Popen("echo $0", executable=sh, shell=True,
1213 stdout=subprocess.PIPE)
Brian Curtin3c6a9512010-11-05 03:58:52 +00001214 self.addCleanup(p.stdout.close)
Stefan Krah9542cc62010-07-19 14:20:53 +00001215 self.assertEqual(p.stdout.read().strip(), bytes(sh, 'ascii'))
1216
Florent Xicluna4886d242010-03-08 13:27:26 +00001217 def _kill_process(self, method, *args):
Florent Xicluna1d8ee3a2010-03-05 20:26:54 +00001218 # Do not inherit file handles from the parent.
1219 # It should fix failures on some platforms.
Antoine Pitrou3d8580f2010-09-20 01:33:21 +00001220 p = subprocess.Popen([sys.executable, "-c", """if 1:
1221 import sys, time
1222 sys.stdout.write('x\\n')
1223 sys.stdout.flush()
1224 time.sleep(30)
1225 """],
1226 close_fds=True,
1227 stdin=subprocess.PIPE,
1228 stdout=subprocess.PIPE,
1229 stderr=subprocess.PIPE)
1230 # Wait for the interpreter to be completely initialized before
1231 # sending any signal.
1232 p.stdout.read(1)
1233 getattr(p, method)(*args)
Florent Xicluna4886d242010-03-08 13:27:26 +00001234 return p
1235
Charles-François Natali53221e32013-01-12 16:52:20 +01001236 @unittest.skipIf(sys.platform.startswith(('netbsd', 'openbsd')),
1237 "Due to known OS bug (issue #16762)")
Antoine Pitrou1f9a8352012-03-11 19:29:12 +01001238 def _kill_dead_process(self, method, *args):
1239 # Do not inherit file handles from the parent.
1240 # It should fix failures on some platforms.
1241 p = subprocess.Popen([sys.executable, "-c", """if 1:
1242 import sys, time
1243 sys.stdout.write('x\\n')
1244 sys.stdout.flush()
1245 """],
1246 close_fds=True,
1247 stdin=subprocess.PIPE,
1248 stdout=subprocess.PIPE,
1249 stderr=subprocess.PIPE)
1250 # Wait for the interpreter to be completely initialized before
1251 # sending any signal.
1252 p.stdout.read(1)
1253 # The process should end after this
1254 time.sleep(1)
1255 # This shouldn't raise even though the child is now dead
1256 getattr(p, method)(*args)
1257 p.communicate()
1258
Florent Xicluna4886d242010-03-08 13:27:26 +00001259 def test_send_signal(self):
1260 p = self._kill_process('send_signal', signal.SIGINT)
Florent Xiclunac049d872010-03-27 22:47:23 +00001261 _, stderr = p.communicate()
1262 self.assertIn(b'KeyboardInterrupt', stderr)
Florent Xiclunaf0cbd822010-03-04 21:50:56 +00001263 self.assertNotEqual(p.wait(), 0)
Christian Heimesa342c012008-04-20 21:01:16 +00001264
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001265 def test_kill(self):
Florent Xicluna4886d242010-03-08 13:27:26 +00001266 p = self._kill_process('kill')
Florent Xiclunac049d872010-03-27 22:47:23 +00001267 _, stderr = p.communicate()
1268 self.assertStderrEqual(stderr, b'')
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001269 self.assertEqual(p.wait(), -signal.SIGKILL)
Tim Peterse718f612004-10-12 21:51:32 +00001270
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001271 def test_terminate(self):
Florent Xicluna4886d242010-03-08 13:27:26 +00001272 p = self._kill_process('terminate')
Florent Xiclunac049d872010-03-27 22:47:23 +00001273 _, stderr = p.communicate()
1274 self.assertStderrEqual(stderr, b'')
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001275 self.assertEqual(p.wait(), -signal.SIGTERM)
1276
Antoine Pitrou1f9a8352012-03-11 19:29:12 +01001277 def test_send_signal_dead(self):
1278 # Sending a signal to a dead process
1279 self._kill_dead_process('send_signal', signal.SIGINT)
1280
1281 def test_kill_dead(self):
1282 # Killing a dead process
1283 self._kill_dead_process('kill')
1284
1285 def test_terminate_dead(self):
1286 # Terminating a dead process
1287 self._kill_dead_process('terminate')
1288
Antoine Pitrouc9c83ba2011-01-03 18:23:55 +00001289 def check_close_std_fds(self, fds):
1290 # Issue #9905: test that subprocess pipes still work properly with
1291 # some standard fds closed
1292 stdin = 0
1293 newfds = []
1294 for a in fds:
1295 b = os.dup(a)
1296 newfds.append(b)
1297 if a == 0:
1298 stdin = b
1299 try:
1300 for fd in fds:
1301 os.close(fd)
1302 out, err = subprocess.Popen([sys.executable, "-c",
1303 'import sys;'
1304 'sys.stdout.write("apple");'
1305 'sys.stdout.flush();'
1306 'sys.stderr.write("orange")'],
1307 stdin=stdin,
1308 stdout=subprocess.PIPE,
1309 stderr=subprocess.PIPE).communicate()
1310 err = support.strip_python_stderr(err)
1311 self.assertEqual((out, err), (b'apple', b'orange'))
1312 finally:
1313 for b, a in zip(newfds, fds):
1314 os.dup2(b, a)
1315 for b in newfds:
1316 os.close(b)
1317
1318 def test_close_fd_0(self):
1319 self.check_close_std_fds([0])
1320
1321 def test_close_fd_1(self):
1322 self.check_close_std_fds([1])
1323
1324 def test_close_fd_2(self):
1325 self.check_close_std_fds([2])
1326
1327 def test_close_fds_0_1(self):
1328 self.check_close_std_fds([0, 1])
1329
1330 def test_close_fds_0_2(self):
1331 self.check_close_std_fds([0, 2])
1332
1333 def test_close_fds_1_2(self):
1334 self.check_close_std_fds([1, 2])
1335
1336 def test_close_fds_0_1_2(self):
1337 # Issue #10806: test that subprocess pipes still work properly with
1338 # all standard fds closed.
1339 self.check_close_std_fds([0, 1, 2])
1340
Antoine Pitrou95aaeee2011-01-03 21:15:48 +00001341 def test_remapping_std_fds(self):
1342 # open up some temporary files
1343 temps = [mkstemp() for i in range(3)]
1344 try:
1345 temp_fds = [fd for fd, fname in temps]
1346
1347 # unlink the files -- we won't need to reopen them
1348 for fd, fname in temps:
1349 os.unlink(fname)
1350
1351 # write some data to what will become stdin, and rewind
1352 os.write(temp_fds[1], b"STDIN")
1353 os.lseek(temp_fds[1], 0, 0)
1354
1355 # move the standard file descriptors out of the way
1356 saved_fds = [os.dup(fd) for fd in range(3)]
1357 try:
1358 # duplicate the file objects over the standard fd's
1359 for fd, temp_fd in enumerate(temp_fds):
1360 os.dup2(temp_fd, fd)
1361
1362 # now use those files in the "wrong" order, so that subprocess
1363 # has to rearrange them in the child
1364 p = subprocess.Popen([sys.executable, "-c",
1365 'import sys; got = sys.stdin.read();'
1366 'sys.stdout.write("got %s"%got); sys.stderr.write("err")'],
1367 stdin=temp_fds[1],
1368 stdout=temp_fds[2],
1369 stderr=temp_fds[0])
1370 p.wait()
1371 finally:
1372 # restore the original fd's underneath sys.stdin, etc.
1373 for std, saved in enumerate(saved_fds):
1374 os.dup2(saved, std)
1375 os.close(saved)
1376
1377 for fd in temp_fds:
1378 os.lseek(fd, 0, 0)
1379
1380 out = os.read(temp_fds[2], 1024)
1381 err = support.strip_python_stderr(os.read(temp_fds[0], 1024))
1382 self.assertEqual(out, b"got STDIN")
1383 self.assertEqual(err, b"err")
1384
1385 finally:
1386 for fd in temp_fds:
1387 os.close(fd)
1388
Ross Lagerwalld98646e2011-07-27 07:16:31 +02001389 def check_swap_fds(self, stdin_no, stdout_no, stderr_no):
1390 # open up some temporary files
1391 temps = [mkstemp() for i in range(3)]
1392 temp_fds = [fd for fd, fname in temps]
1393 try:
1394 # unlink the files -- we won't need to reopen them
1395 for fd, fname in temps:
1396 os.unlink(fname)
1397
1398 # save a copy of the standard file descriptors
1399 saved_fds = [os.dup(fd) for fd in range(3)]
1400 try:
1401 # duplicate the temp files over the standard fd's 0, 1, 2
1402 for fd, temp_fd in enumerate(temp_fds):
1403 os.dup2(temp_fd, fd)
1404
1405 # write some data to what will become stdin, and rewind
1406 os.write(stdin_no, b"STDIN")
1407 os.lseek(stdin_no, 0, 0)
1408
1409 # now use those files in the given order, so that subprocess
1410 # has to rearrange them in the child
1411 p = subprocess.Popen([sys.executable, "-c",
1412 'import sys; got = sys.stdin.read();'
1413 'sys.stdout.write("got %s"%got); sys.stderr.write("err")'],
1414 stdin=stdin_no,
1415 stdout=stdout_no,
1416 stderr=stderr_no)
1417 p.wait()
1418
1419 for fd in temp_fds:
1420 os.lseek(fd, 0, 0)
1421
1422 out = os.read(stdout_no, 1024)
1423 err = support.strip_python_stderr(os.read(stderr_no, 1024))
1424 finally:
1425 for std, saved in enumerate(saved_fds):
1426 os.dup2(saved, std)
1427 os.close(saved)
1428
1429 self.assertEqual(out, b"got STDIN")
1430 self.assertEqual(err, b"err")
1431
1432 finally:
1433 for fd in temp_fds:
1434 os.close(fd)
1435
1436 # When duping fds, if there arises a situation where one of the fds is
1437 # either 0, 1 or 2, it is possible that it is overwritten (#12607).
1438 # This tests all combinations of this.
1439 def test_swap_fds(self):
1440 self.check_swap_fds(0, 1, 2)
1441 self.check_swap_fds(0, 2, 1)
1442 self.check_swap_fds(1, 0, 2)
1443 self.check_swap_fds(1, 2, 0)
1444 self.check_swap_fds(2, 0, 1)
1445 self.check_swap_fds(2, 1, 0)
1446
Victor Stinner13bb71c2010-04-23 21:41:56 +00001447 def test_surrogates_error_message(self):
Victor Stinner4d078042010-04-23 19:28:32 +00001448 def prepare():
1449 raise ValueError("surrogate:\uDCff")
1450
1451 try:
1452 subprocess.call(
1453 [sys.executable, "-c", "pass"],
1454 preexec_fn=prepare)
1455 except ValueError as err:
1456 # Pure Python implementations keeps the message
1457 self.assertIsNone(subprocess._posixsubprocess)
1458 self.assertEqual(str(err), "surrogate:\uDCff")
1459 except RuntimeError as err:
1460 # _posixsubprocess uses a default message
1461 self.assertIsNotNone(subprocess._posixsubprocess)
1462 self.assertEqual(str(err), "Exception occurred in preexec_fn.")
1463 else:
1464 self.fail("Expected ValueError or RuntimeError")
1465
Victor Stinner13bb71c2010-04-23 21:41:56 +00001466 def test_undecodable_env(self):
1467 for key, value in (('test', 'abc\uDCFF'), ('test\uDCFF', '42')):
Victor Stinner13bb71c2010-04-23 21:41:56 +00001468 # test str with surrogates
Antoine Pitroufb8db8f2010-09-19 22:46:05 +00001469 script = "import os; print(ascii(os.getenv(%s)))" % repr(key)
Victor Stinnerce2d24d2010-04-23 22:55:39 +00001470 env = os.environ.copy()
1471 env[key] = value
Victor Stinner89f3ad12010-10-14 10:43:31 +00001472 # Use C locale to get ascii for the locale encoding to force
1473 # surrogate-escaping of \xFF in the child process; otherwise it can
1474 # be decoded as-is if the default locale is latin-1.
Victor Stinnerebc78d22010-10-14 10:38:17 +00001475 env['LC_ALL'] = 'C'
Victor Stinner13bb71c2010-04-23 21:41:56 +00001476 stdout = subprocess.check_output(
1477 [sys.executable, "-c", script],
Victor Stinnerce2d24d2010-04-23 22:55:39 +00001478 env=env)
Victor Stinner13bb71c2010-04-23 21:41:56 +00001479 stdout = stdout.rstrip(b'\n\r')
Ezio Melottib3aedd42010-11-20 19:04:17 +00001480 self.assertEqual(stdout.decode('ascii'), ascii(value))
Victor Stinner13bb71c2010-04-23 21:41:56 +00001481
1482 # test bytes
1483 key = key.encode("ascii", "surrogateescape")
1484 value = value.encode("ascii", "surrogateescape")
Antoine Pitroufb8db8f2010-09-19 22:46:05 +00001485 script = "import os; print(ascii(os.getenvb(%s)))" % repr(key)
Victor Stinnerce2d24d2010-04-23 22:55:39 +00001486 env = os.environ.copy()
1487 env[key] = value
Victor Stinner13bb71c2010-04-23 21:41:56 +00001488 stdout = subprocess.check_output(
1489 [sys.executable, "-c", script],
Victor Stinnerce2d24d2010-04-23 22:55:39 +00001490 env=env)
Victor Stinner13bb71c2010-04-23 21:41:56 +00001491 stdout = stdout.rstrip(b'\n\r')
Ezio Melottib3aedd42010-11-20 19:04:17 +00001492 self.assertEqual(stdout.decode('ascii'), ascii(value))
Victor Stinner13bb71c2010-04-23 21:41:56 +00001493
Victor Stinnerb745a742010-05-18 17:17:23 +00001494 def test_bytes_program(self):
1495 abs_program = os.fsencode(sys.executable)
1496 path, program = os.path.split(sys.executable)
1497 program = os.fsencode(program)
1498
1499 # absolute bytes path
1500 exitcode = subprocess.call([abs_program, "-c", "pass"])
Ezio Melottib3aedd42010-11-20 19:04:17 +00001501 self.assertEqual(exitcode, 0)
Victor Stinnerb745a742010-05-18 17:17:23 +00001502
1503 # bytes program, unicode PATH
1504 env = os.environ.copy()
1505 env["PATH"] = path
1506 exitcode = subprocess.call([program, "-c", "pass"], env=env)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001507 self.assertEqual(exitcode, 0)
Victor Stinnerb745a742010-05-18 17:17:23 +00001508
1509 # bytes program, bytes PATH
1510 envb = os.environb.copy()
1511 envb[b"PATH"] = os.fsencode(path)
1512 exitcode = subprocess.call([program, "-c", "pass"], env=envb)
Ezio Melottib3aedd42010-11-20 19:04:17 +00001513 self.assertEqual(exitcode, 0)
Victor Stinnerb745a742010-05-18 17:17:23 +00001514
Gregory P. Smith51ee2702010-12-13 07:59:39 +00001515 def test_pipe_cloexec(self):
1516 sleeper = support.findfile("input_reader.py", subdir="subprocessdata")
1517 fd_status = support.findfile("fd_status.py", subdir="subprocessdata")
1518
1519 p1 = subprocess.Popen([sys.executable, sleeper],
1520 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1521 stderr=subprocess.PIPE, close_fds=False)
1522
1523 self.addCleanup(p1.communicate, b'')
1524
1525 p2 = subprocess.Popen([sys.executable, fd_status],
1526 stdout=subprocess.PIPE, close_fds=False)
1527
1528 output, error = p2.communicate()
1529 result_fds = set(map(int, output.split(b',')))
1530 unwanted_fds = set([p1.stdin.fileno(), p1.stdout.fileno(),
1531 p1.stderr.fileno()])
1532
1533 self.assertFalse(result_fds & unwanted_fds,
1534 "Expected no fds from %r to be open in child, "
1535 "found %r" %
1536 (unwanted_fds, result_fds & unwanted_fds))
1537
1538 def test_pipe_cloexec_real_tools(self):
1539 qcat = support.findfile("qcat.py", subdir="subprocessdata")
1540 qgrep = support.findfile("qgrep.py", subdir="subprocessdata")
1541
1542 subdata = b'zxcvbn'
1543 data = subdata * 4 + b'\n'
1544
1545 p1 = subprocess.Popen([sys.executable, qcat],
1546 stdin=subprocess.PIPE, stdout=subprocess.PIPE,
1547 close_fds=False)
1548
1549 p2 = subprocess.Popen([sys.executable, qgrep, subdata],
1550 stdin=p1.stdout, stdout=subprocess.PIPE,
1551 close_fds=False)
1552
1553 self.addCleanup(p1.wait)
1554 self.addCleanup(p2.wait)
Gregory P. Smith886455c2012-01-21 22:05:10 -08001555 def kill_p1():
1556 try:
1557 p1.terminate()
1558 except ProcessLookupError:
1559 pass
1560 def kill_p2():
1561 try:
1562 p2.terminate()
1563 except ProcessLookupError:
1564 pass
1565 self.addCleanup(kill_p1)
1566 self.addCleanup(kill_p2)
Gregory P. Smith51ee2702010-12-13 07:59:39 +00001567
1568 p1.stdin.write(data)
1569 p1.stdin.close()
1570
1571 readfiles, ignored1, ignored2 = select.select([p2.stdout], [], [], 10)
1572
1573 self.assertTrue(readfiles, "The child hung")
1574 self.assertEqual(p2.stdout.read(), data)
1575
Victor Stinnerfaa8c132011-01-03 16:36:00 +00001576 p1.stdout.close()
1577 p2.stdout.close()
1578
Gregory P. Smith51ee2702010-12-13 07:59:39 +00001579 def test_close_fds(self):
1580 fd_status = support.findfile("fd_status.py", subdir="subprocessdata")
1581
1582 fds = os.pipe()
1583 self.addCleanup(os.close, fds[0])
1584 self.addCleanup(os.close, fds[1])
1585
1586 open_fds = set(fds)
Gregory P. Smith8facece2012-01-21 14:01:08 -08001587 # add a bunch more fds
1588 for _ in range(9):
1589 fd = os.open("/dev/null", os.O_RDONLY)
1590 self.addCleanup(os.close, fd)
1591 open_fds.add(fd)
Gregory P. Smith51ee2702010-12-13 07:59:39 +00001592
1593 p = subprocess.Popen([sys.executable, fd_status],
1594 stdout=subprocess.PIPE, close_fds=False)
1595 output, ignored = p.communicate()
1596 remaining_fds = set(map(int, output.split(b',')))
1597
1598 self.assertEqual(remaining_fds & open_fds, open_fds,
1599 "Some fds were closed")
1600
1601 p = subprocess.Popen([sys.executable, fd_status],
1602 stdout=subprocess.PIPE, close_fds=True)
1603 output, ignored = p.communicate()
1604 remaining_fds = set(map(int, output.split(b',')))
1605
1606 self.assertFalse(remaining_fds & open_fds,
1607 "Some fds were left open")
1608 self.assertIn(1, remaining_fds, "Subprocess failed")
1609
Gregory P. Smith8facece2012-01-21 14:01:08 -08001610 # Keep some of the fd's we opened open in the subprocess.
1611 # This tests _posixsubprocess.c's proper handling of fds_to_keep.
1612 fds_to_keep = set(open_fds.pop() for _ in range(8))
1613 p = subprocess.Popen([sys.executable, fd_status],
1614 stdout=subprocess.PIPE, close_fds=True,
1615 pass_fds=())
1616 output, ignored = p.communicate()
1617 remaining_fds = set(map(int, output.split(b',')))
1618
1619 self.assertFalse(remaining_fds & fds_to_keep & open_fds,
1620 "Some fds not in pass_fds were left open")
1621 self.assertIn(1, remaining_fds, "Subprocess failed")
1622
Victor Stinner88701e22011-06-01 13:13:04 +02001623 # Mac OS X Tiger (10.4) has a kernel bug: sometimes, the file
1624 # descriptor of a pipe closed in the parent process is valid in the
1625 # child process according to fstat(), but the mode of the file
1626 # descriptor is invalid, and read or write raise an error.
1627 @support.requires_mac_ver(10, 5)
Gregory P. Smith8edd99d2010-12-14 13:43:30 +00001628 def test_pass_fds(self):
1629 fd_status = support.findfile("fd_status.py", subdir="subprocessdata")
1630
1631 open_fds = set()
1632
1633 for x in range(5):
1634 fds = os.pipe()
1635 self.addCleanup(os.close, fds[0])
1636 self.addCleanup(os.close, fds[1])
1637 open_fds.update(fds)
1638
1639 for fd in open_fds:
1640 p = subprocess.Popen([sys.executable, fd_status],
1641 stdout=subprocess.PIPE, close_fds=True,
1642 pass_fds=(fd, ))
1643 output, ignored = p.communicate()
1644
1645 remaining_fds = set(map(int, output.split(b',')))
1646 to_be_closed = open_fds - {fd}
1647
1648 self.assertIn(fd, remaining_fds, "fd to be passed not passed")
1649 self.assertFalse(remaining_fds & to_be_closed,
1650 "fd to be closed passed")
1651
1652 # pass_fds overrides close_fds with a warning.
1653 with self.assertWarns(RuntimeWarning) as context:
1654 self.assertFalse(subprocess.call(
1655 [sys.executable, "-c", "import sys; sys.exit(0)"],
1656 close_fds=False, pass_fds=(fd, )))
1657 self.assertIn('overriding close_fds', str(context.warning))
1658
Gregory P. Smithe14e9c22011-03-15 14:55:17 -04001659 def test_stdout_stdin_are_single_inout_fd(self):
1660 with io.open(os.devnull, "r+") as inout:
1661 p = subprocess.Popen([sys.executable, "-c", "import sys; sys.exit(0)"],
1662 stdout=inout, stdin=inout)
1663 p.wait()
1664
1665 def test_stdout_stderr_are_single_inout_fd(self):
1666 with io.open(os.devnull, "r+") as inout:
1667 p = subprocess.Popen([sys.executable, "-c", "import sys; sys.exit(0)"],
1668 stdout=inout, stderr=inout)
1669 p.wait()
1670
1671 def test_stderr_stdin_are_single_inout_fd(self):
1672 with io.open(os.devnull, "r+") as inout:
1673 p = subprocess.Popen([sys.executable, "-c", "import sys; sys.exit(0)"],
1674 stderr=inout, stdin=inout)
1675 p.wait()
1676
Gregory P. Smithe85db2b2010-12-14 14:38:00 +00001677 def test_wait_when_sigchild_ignored(self):
1678 # NOTE: sigchild_ignore.py may not be an effective test on all OSes.
1679 sigchild_ignore = support.findfile("sigchild_ignore.py",
1680 subdir="subprocessdata")
1681 p = subprocess.Popen([sys.executable, sigchild_ignore],
1682 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1683 stdout, stderr = p.communicate()
1684 self.assertEqual(0, p.returncode, "sigchild_ignore.py exited"
Gregory P. Smitha80f4fb2010-12-14 15:23:02 +00001685 " non-zero with this error:\n%s" %
1686 stderr.decode('utf8'))
Gregory P. Smithe85db2b2010-12-14 14:38:00 +00001687
Antoine Pitrou7b98d022011-03-19 17:04:13 +01001688 def test_select_unbuffered(self):
1689 # Issue #11459: bufsize=0 should really set the pipes as
1690 # unbuffered (and therefore let select() work properly).
1691 select = support.import_module("select")
1692 p = subprocess.Popen([sys.executable, "-c",
1693 'import sys;'
1694 'sys.stdout.write("apple")'],
1695 stdout=subprocess.PIPE,
1696 bufsize=0)
1697 f = p.stdout
Ross Lagerwall17ace7a2011-03-26 21:21:46 +02001698 self.addCleanup(f.close)
Antoine Pitrou7b98d022011-03-19 17:04:13 +01001699 try:
1700 self.assertEqual(f.read(4), b"appl")
1701 self.assertIn(f, select.select([f], [], [], 0.0)[0])
1702 finally:
1703 p.wait()
1704
Charles-François Natali134a8ba2011-08-18 18:49:39 +02001705 def test_zombie_fast_process_del(self):
1706 # Issue #12650: on Unix, if Popen.__del__() was called before the
1707 # process exited, it wouldn't be added to subprocess._active, and would
1708 # remain a zombie.
1709 # spawn a Popen, and delete its reference before it exits
1710 p = subprocess.Popen([sys.executable, "-c",
1711 'import sys, time;'
1712 'time.sleep(0.2)'],
1713 stdout=subprocess.PIPE,
1714 stderr=subprocess.PIPE)
Nadeem Vawda0d7cda32011-08-19 05:12:01 +02001715 self.addCleanup(p.stdout.close)
1716 self.addCleanup(p.stderr.close)
Charles-François Natali134a8ba2011-08-18 18:49:39 +02001717 ident = id(p)
1718 pid = p.pid
1719 del p
1720 # check that p is in the active processes list
1721 self.assertIn(ident, [id(o) for o in subprocess._active])
1722
Charles-François Natali134a8ba2011-08-18 18:49:39 +02001723 def test_leak_fast_process_del_killed(self):
1724 # Issue #12650: on Unix, if Popen.__del__() was called before the
1725 # process exited, and the process got killed by a signal, it would never
1726 # be removed from subprocess._active, which triggered a FD and memory
1727 # leak.
1728 # spawn a Popen, delete its reference and kill it
1729 p = subprocess.Popen([sys.executable, "-c",
1730 'import time;'
1731 'time.sleep(3)'],
1732 stdout=subprocess.PIPE,
1733 stderr=subprocess.PIPE)
Nadeem Vawda0d7cda32011-08-19 05:12:01 +02001734 self.addCleanup(p.stdout.close)
1735 self.addCleanup(p.stderr.close)
Charles-François Natali134a8ba2011-08-18 18:49:39 +02001736 ident = id(p)
1737 pid = p.pid
1738 del p
1739 os.kill(pid, signal.SIGKILL)
1740 # check that p is in the active processes list
1741 self.assertIn(ident, [id(o) for o in subprocess._active])
1742
1743 # let some time for the process to exit, and create a new Popen: this
1744 # should trigger the wait() of p
1745 time.sleep(0.2)
1746 with self.assertRaises(EnvironmentError) as c:
1747 with subprocess.Popen(['nonexisting_i_hope'],
1748 stdout=subprocess.PIPE,
1749 stderr=subprocess.PIPE) as proc:
1750 pass
1751 # p should have been wait()ed on, and removed from the _active list
1752 self.assertRaises(OSError, os.waitpid, pid, 0)
1753 self.assertNotIn(ident, [id(o) for o in subprocess._active])
1754
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001755
Florent Xiclunaf0cbd822010-03-04 21:50:56 +00001756@unittest.skipUnless(mswindows, "Windows specific tests")
Florent Xiclunac049d872010-03-27 22:47:23 +00001757class Win32ProcessTestCase(BaseTestCase):
Florent Xiclunaf0cbd822010-03-04 21:50:56 +00001758
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001759 def test_startupinfo(self):
1760 # startupinfo argument
1761 # We uses hardcoded constants, because we do not want to
1762 # depend on win32all.
1763 STARTF_USESHOWWINDOW = 1
1764 SW_MAXIMIZE = 3
1765 startupinfo = subprocess.STARTUPINFO()
1766 startupinfo.dwFlags = STARTF_USESHOWWINDOW
1767 startupinfo.wShowWindow = SW_MAXIMIZE
1768 # Since Python is a console process, it won't be affected
1769 # by wShowWindow, but the argument should be silently
1770 # ignored
1771 subprocess.call([sys.executable, "-c", "import sys; sys.exit(0)"],
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001772 startupinfo=startupinfo)
1773
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001774 def test_creationflags(self):
1775 # creationflags argument
1776 CREATE_NEW_CONSOLE = 16
1777 sys.stderr.write(" a DOS box should flash briefly ...\n")
1778 subprocess.call(sys.executable +
1779 ' -c "import time; time.sleep(0.25)"',
1780 creationflags=CREATE_NEW_CONSOLE)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001781
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001782 def test_invalid_args(self):
1783 # invalid arguments should raise ValueError
1784 self.assertRaises(ValueError, subprocess.call,
1785 [sys.executable, "-c",
1786 "import sys; sys.exit(47)"],
1787 preexec_fn=lambda: 1)
1788 self.assertRaises(ValueError, subprocess.call,
1789 [sys.executable, "-c",
1790 "import sys; sys.exit(47)"],
1791 stdout=subprocess.PIPE,
1792 close_fds=True)
1793
1794 def test_close_fds(self):
1795 # close file descriptors
1796 rc = subprocess.call([sys.executable, "-c",
1797 "import sys; sys.exit(47)"],
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001798 close_fds=True)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001799 self.assertEqual(rc, 47)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001800
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001801 def test_shell_sequence(self):
1802 # Run command through the shell (sequence)
1803 newenv = os.environ.copy()
1804 newenv["FRUIT"] = "physalis"
1805 p = subprocess.Popen(["set"], shell=1,
1806 stdout=subprocess.PIPE,
1807 env=newenv)
Brian Curtin19a53792010-11-05 17:09:05 +00001808 self.addCleanup(p.stdout.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001809 self.assertIn(b"physalis", p.stdout.read())
Guido van Rossume7ba4952007-06-06 23:52:48 +00001810
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001811 def test_shell_string(self):
1812 # Run command through the shell (string)
1813 newenv = os.environ.copy()
1814 newenv["FRUIT"] = "physalis"
1815 p = subprocess.Popen("set", shell=1,
1816 stdout=subprocess.PIPE,
1817 env=newenv)
Brian Curtin19a53792010-11-05 17:09:05 +00001818 self.addCleanup(p.stdout.close)
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001819 self.assertIn(b"physalis", p.stdout.read())
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001820
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001821 def test_call_string(self):
1822 # call() function with string argument on Windows
1823 rc = subprocess.call(sys.executable +
1824 ' -c "import sys; sys.exit(47)"')
1825 self.assertEqual(rc, 47)
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001826
Florent Xicluna4886d242010-03-08 13:27:26 +00001827 def _kill_process(self, method, *args):
1828 # Some win32 buildbot raises EOFError if stdin is inherited
Antoine Pitroua4024e22010-09-24 18:57:01 +00001829 p = subprocess.Popen([sys.executable, "-c", """if 1:
1830 import sys, time
1831 sys.stdout.write('x\\n')
1832 sys.stdout.flush()
1833 time.sleep(30)
1834 """],
1835 stdin=subprocess.PIPE,
1836 stdout=subprocess.PIPE,
1837 stderr=subprocess.PIPE)
Brian Curtin19a53792010-11-05 17:09:05 +00001838 self.addCleanup(p.stdout.close)
1839 self.addCleanup(p.stderr.close)
1840 self.addCleanup(p.stdin.close)
Antoine Pitroua4024e22010-09-24 18:57:01 +00001841 # Wait for the interpreter to be completely initialized before
1842 # sending any signal.
1843 p.stdout.read(1)
1844 getattr(p, method)(*args)
Florent Xiclunac049d872010-03-27 22:47:23 +00001845 _, stderr = p.communicate()
1846 self.assertStderrEqual(stderr, b'')
Antoine Pitroua4024e22010-09-24 18:57:01 +00001847 returncode = p.wait()
Florent Xicluna4886d242010-03-08 13:27:26 +00001848 self.assertNotEqual(returncode, 0)
1849
Antoine Pitrou1f9a8352012-03-11 19:29:12 +01001850 def _kill_dead_process(self, method, *args):
1851 p = subprocess.Popen([sys.executable, "-c", """if 1:
1852 import sys, time
1853 sys.stdout.write('x\\n')
1854 sys.stdout.flush()
1855 sys.exit(42)
1856 """],
1857 stdin=subprocess.PIPE,
1858 stdout=subprocess.PIPE,
1859 stderr=subprocess.PIPE)
1860 self.addCleanup(p.stdout.close)
1861 self.addCleanup(p.stderr.close)
1862 self.addCleanup(p.stdin.close)
1863 # Wait for the interpreter to be completely initialized before
1864 # sending any signal.
1865 p.stdout.read(1)
1866 # The process should end after this
1867 time.sleep(1)
1868 # This shouldn't raise even though the child is now dead
1869 getattr(p, method)(*args)
1870 _, stderr = p.communicate()
1871 self.assertStderrEqual(stderr, b'')
1872 rc = p.wait()
1873 self.assertEqual(rc, 42)
1874
Florent Xicluna4886d242010-03-08 13:27:26 +00001875 def test_send_signal(self):
1876 self._kill_process('send_signal', signal.SIGTERM)
Christian Heimesa342c012008-04-20 21:01:16 +00001877
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001878 def test_kill(self):
Florent Xicluna4886d242010-03-08 13:27:26 +00001879 self._kill_process('kill')
Christian Heimesa342c012008-04-20 21:01:16 +00001880
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001881 def test_terminate(self):
Florent Xicluna4886d242010-03-08 13:27:26 +00001882 self._kill_process('terminate')
Christian Heimesa342c012008-04-20 21:01:16 +00001883
Antoine Pitrou1f9a8352012-03-11 19:29:12 +01001884 def test_send_signal_dead(self):
1885 self._kill_dead_process('send_signal', signal.SIGTERM)
1886
1887 def test_kill_dead(self):
1888 self._kill_dead_process('kill')
1889
1890 def test_terminate_dead(self):
1891 self._kill_dead_process('terminate')
1892
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00001893
Brett Cannona23810f2008-05-26 19:04:21 +00001894# The module says:
1895# "NB This only works (and is only relevant) for UNIX."
1896#
1897# Actually, getoutput should work on any platform with an os.popen, but
1898# I'll take the comment as given, and skip this suite.
Florent Xiclunaf0cbd822010-03-04 21:50:56 +00001899@unittest.skipUnless(os.name == 'posix', "only relevant for UNIX")
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001900class CommandTests(unittest.TestCase):
1901 def test_getoutput(self):
1902 self.assertEqual(subprocess.getoutput('echo xyzzy'), 'xyzzy')
1903 self.assertEqual(subprocess.getstatusoutput('echo xyzzy'),
1904 (0, 'xyzzy'))
Brett Cannona23810f2008-05-26 19:04:21 +00001905
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001906 # we use mkdtemp in the next line to create an empty directory
1907 # under our exclusive control; from that, we can invent a pathname
1908 # that we _know_ won't exist. This is guaranteed to fail.
1909 dir = None
1910 try:
1911 dir = tempfile.mkdtemp()
1912 name = os.path.join(dir, "foo")
Brett Cannona23810f2008-05-26 19:04:21 +00001913
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001914 status, output = subprocess.getstatusoutput('cat ' + name)
1915 self.assertNotEqual(status, 0)
1916 finally:
1917 if dir is not None:
1918 os.rmdir(dir)
Brett Cannona23810f2008-05-26 19:04:21 +00001919
Gregory P. Smithd06fa472009-07-04 02:46:54 +00001920
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001921@unittest.skipUnless(getattr(subprocess, '_has_poll', False),
1922 "poll system call not supported")
1923class ProcessTestCaseNoPoll(ProcessTestCase):
1924 def setUp(self):
1925 subprocess._has_poll = False
1926 ProcessTestCase.setUp(self)
Gregory P. Smithd06fa472009-07-04 02:46:54 +00001927
Florent Xiclunab1e94e82010-02-27 22:12:37 +00001928 def tearDown(self):
1929 subprocess._has_poll = True
1930 ProcessTestCase.tearDown(self)
Gregory P. Smithd06fa472009-07-04 02:46:54 +00001931
1932
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001933@unittest.skipUnless(getattr(subprocess, '_posixsubprocess', False),
1934 "_posixsubprocess extension module not found.")
1935class ProcessTestCasePOSIXPurePython(ProcessTestCase, POSIXProcessTestCase):
Gregory P. Smith7439e7b2011-05-28 09:06:02 -07001936 @classmethod
1937 def setUpClass(cls):
1938 global subprocess
1939 assert subprocess._posixsubprocess
1940 # Reimport subprocess while forcing _posixsubprocess to not exist.
1941 with support.check_warnings(('.*_posixsubprocess .* not being used.*',
1942 RuntimeWarning)):
1943 subprocess = support.import_fresh_module(
1944 'subprocess', blocked=['_posixsubprocess'])
1945 assert not subprocess._posixsubprocess
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001946
Gregory P. Smith7439e7b2011-05-28 09:06:02 -07001947 @classmethod
1948 def tearDownClass(cls):
1949 global subprocess
1950 # Reimport subprocess as it should be, restoring order to the universe.
1951 subprocess = support.import_fresh_module('subprocess')
1952 assert subprocess._posixsubprocess
Gregory P. Smithfb94c5f2010-03-14 06:49:55 +00001953
1954
Gregory P. Smitha59c59f2010-03-01 00:17:40 +00001955class HelperFunctionTests(unittest.TestCase):
Gregory P. Smithaf6d3b82010-03-01 02:56:44 +00001956 @unittest.skipIf(mswindows, "errno and EINTR make no sense on windows")
Gregory P. Smitha59c59f2010-03-01 00:17:40 +00001957 def test_eintr_retry_call(self):
1958 record_calls = []
1959 def fake_os_func(*args):
1960 record_calls.append(args)
1961 if len(record_calls) == 2:
1962 raise OSError(errno.EINTR, "fake interrupted system call")
1963 return tuple(reversed(args))
1964
1965 self.assertEqual((999, 256),
1966 subprocess._eintr_retry_call(fake_os_func, 256, 999))
1967 self.assertEqual([(256, 999)], record_calls)
1968 # This time there will be an EINTR so it will loop once.
1969 self.assertEqual((666,),
1970 subprocess._eintr_retry_call(fake_os_func, 666))
1971 self.assertEqual([(256, 999), (666,), (666,)], record_calls)
1972
1973
Tim Golden126c2962010-08-11 14:20:40 +00001974@unittest.skipUnless(mswindows, "Windows-specific tests")
1975class CommandsWithSpaces (BaseTestCase):
1976
1977 def setUp(self):
1978 super().setUp()
1979 f, fname = mkstemp(".py", "te st")
1980 self.fname = fname.lower ()
1981 os.write(f, b"import sys;"
1982 b"sys.stdout.write('%d %s' % (len(sys.argv), [a.lower () for a in sys.argv]))"
1983 )
1984 os.close(f)
1985
1986 def tearDown(self):
1987 os.remove(self.fname)
1988 super().tearDown()
1989
1990 def with_spaces(self, *args, **kwargs):
1991 kwargs['stdout'] = subprocess.PIPE
1992 p = subprocess.Popen(*args, **kwargs)
Brian Curtin19a53792010-11-05 17:09:05 +00001993 self.addCleanup(p.stdout.close)
Tim Golden126c2962010-08-11 14:20:40 +00001994 self.assertEqual(
1995 p.stdout.read ().decode("mbcs"),
1996 "2 [%r, 'ab cd']" % self.fname
1997 )
1998
1999 def test_shell_string_with_spaces(self):
2000 # call() function with string argument with spaces on Windows
Brian Curtind835cf12010-08-13 20:42:57 +00002001 self.with_spaces('"%s" "%s" "%s"' % (sys.executable, self.fname,
2002 "ab cd"), shell=1)
Tim Golden126c2962010-08-11 14:20:40 +00002003
2004 def test_shell_sequence_with_spaces(self):
2005 # call() function with sequence argument with spaces on Windows
Brian Curtind835cf12010-08-13 20:42:57 +00002006 self.with_spaces([sys.executable, self.fname, "ab cd"], shell=1)
Tim Golden126c2962010-08-11 14:20:40 +00002007
2008 def test_noshell_string_with_spaces(self):
2009 # call() function with string argument with spaces on Windows
2010 self.with_spaces('"%s" "%s" "%s"' % (sys.executable, self.fname,
2011 "ab cd"))
2012
2013 def test_noshell_sequence_with_spaces(self):
2014 # call() function with sequence argument with spaces on Windows
2015 self.with_spaces([sys.executable, self.fname, "ab cd"])
2016
Brian Curtin79cdb662010-12-03 02:46:02 +00002017
Georg Brandla86b2622012-02-20 21:34:57 +01002018class ContextManagerTests(BaseTestCase):
Brian Curtin79cdb662010-12-03 02:46:02 +00002019
2020 def test_pipe(self):
2021 with subprocess.Popen([sys.executable, "-c",
2022 "import sys;"
2023 "sys.stdout.write('stdout');"
2024 "sys.stderr.write('stderr');"],
2025 stdout=subprocess.PIPE,
2026 stderr=subprocess.PIPE) as proc:
2027 self.assertEqual(proc.stdout.read(), b"stdout")
2028 self.assertStderrEqual(proc.stderr.read(), b"stderr")
2029
2030 self.assertTrue(proc.stdout.closed)
2031 self.assertTrue(proc.stderr.closed)
2032
2033 def test_returncode(self):
2034 with subprocess.Popen([sys.executable, "-c",
2035 "import sys; sys.exit(100)"]) as proc:
Gregory P. Smithc9557af2011-05-11 22:18:23 -07002036 pass
2037 # __exit__ calls wait(), so the returncode should be set
Brian Curtin79cdb662010-12-03 02:46:02 +00002038 self.assertEqual(proc.returncode, 100)
2039
2040 def test_communicate_stdin(self):
2041 with subprocess.Popen([sys.executable, "-c",
2042 "import sys;"
2043 "sys.exit(sys.stdin.read() == 'context')"],
2044 stdin=subprocess.PIPE) as proc:
2045 proc.communicate(b"context")
2046 self.assertEqual(proc.returncode, 1)
2047
2048 def test_invalid_args(self):
2049 with self.assertRaises(EnvironmentError) as c:
2050 with subprocess.Popen(['nonexisting_i_hope'],
2051 stdout=subprocess.PIPE,
2052 stderr=subprocess.PIPE) as proc:
2053 pass
2054
Andrew Svetlov57a12332012-12-26 23:31:45 +02002055 self.assertEqual(c.exception.errno, errno.ENOENT)
Brian Curtin79cdb662010-12-03 02:46:02 +00002056
2057
Gregory P. Smith961e0e82011-03-15 15:43:39 -04002058def test_main():
2059 unit_tests = (ProcessTestCase,
2060 POSIXProcessTestCase,
2061 Win32ProcessTestCase,
2062 ProcessTestCasePOSIXPurePython,
2063 CommandTests,
2064 ProcessTestCaseNoPoll,
2065 HelperFunctionTests,
2066 CommandsWithSpaces,
Antoine Pitrouab85ff32011-07-23 22:03:45 +02002067 ContextManagerTests,
2068 )
Gregory P. Smith961e0e82011-03-15 15:43:39 -04002069
2070 support.run_unittest(*unit_tests)
2071 support.reap_children()
2072
Fredrik Lundh5b3687d2004-10-12 15:26:28 +00002073if __name__ == "__main__":
Gregory P. Smithe14e9c22011-03-15 14:55:17 -04002074 unittest.main()