|
|
|
@ -1489,10 +1489,10 @@ class PosixGroupsTester(unittest.TestCase): |
|
|
|
self.assertListEqual(groups, posix.getgroups()) |
|
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") |
|
|
|
class TestPosixSpawn(unittest.TestCase): |
|
|
|
# Program which does nothing and exit with status 0 (success) |
|
|
|
class _PosixSpawnMixin: |
|
|
|
# Program which does nothing and exits with status 0 (success) |
|
|
|
NOOP_PROGRAM = (sys.executable, '-I', '-S', '-c', 'pass') |
|
|
|
spawn_func = None |
|
|
|
|
|
|
|
def python_args(self, *args): |
|
|
|
# Disable site module to avoid side effects. For example, |
|
|
|
@ -1511,7 +1511,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
pidfile.write(str(os.getpid())) |
|
|
|
""" |
|
|
|
args = self.python_args('-c', script) |
|
|
|
pid = posix.posix_spawn(args[0], args, os.environ) |
|
|
|
pid = self.spawn_func(args[0], args, os.environ) |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
with open(pidfile) as f: |
|
|
|
self.assertEqual(f.read(), str(pid)) |
|
|
|
@ -1519,9 +1519,9 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
def test_no_such_executable(self): |
|
|
|
no_such_executable = 'no_such_executable' |
|
|
|
try: |
|
|
|
pid = posix.posix_spawn(no_such_executable, |
|
|
|
[no_such_executable], |
|
|
|
os.environ) |
|
|
|
pid = self.spawn_func(no_such_executable, |
|
|
|
[no_such_executable], |
|
|
|
os.environ) |
|
|
|
except FileNotFoundError as exc: |
|
|
|
self.assertEqual(exc.filename, no_such_executable) |
|
|
|
else: |
|
|
|
@ -1538,14 +1538,14 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
envfile.write(os.environ['foo']) |
|
|
|
""" |
|
|
|
args = self.python_args('-c', script) |
|
|
|
pid = posix.posix_spawn(args[0], args, |
|
|
|
{**os.environ, 'foo': 'bar'}) |
|
|
|
pid = self.spawn_func(args[0], args, |
|
|
|
{**os.environ, 'foo': 'bar'}) |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
with open(envfile) as f: |
|
|
|
self.assertEqual(f.read(), 'bar') |
|
|
|
|
|
|
|
def test_empty_file_actions(self): |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
self.NOOP_PROGRAM[0], |
|
|
|
self.NOOP_PROGRAM, |
|
|
|
os.environ, |
|
|
|
@ -1554,7 +1554,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
|
|
|
|
def test_resetids_explicit_default(self): |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', 'pass'], |
|
|
|
os.environ, |
|
|
|
@ -1563,7 +1563,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
|
|
|
|
def test_resetids(self): |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', 'pass'], |
|
|
|
os.environ, |
|
|
|
@ -1573,12 +1573,12 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
|
|
|
|
def test_resetids_wrong_type(self): |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, resetids=None) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, resetids=None) |
|
|
|
|
|
|
|
def test_setpgroup(self): |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', 'pass'], |
|
|
|
os.environ, |
|
|
|
@ -1588,9 +1588,9 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
|
|
|
|
def test_setpgroup_wrong_type(self): |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setpgroup="023") |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setpgroup="023") |
|
|
|
|
|
|
|
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), |
|
|
|
'need signal.pthread_sigmask()') |
|
|
|
@ -1599,7 +1599,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
import signal |
|
|
|
signal.raise_signal(signal.SIGUSR1)""") |
|
|
|
|
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', code], |
|
|
|
os.environ, |
|
|
|
@ -1609,18 +1609,18 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
|
|
|
|
def test_setsigmask_wrong_type(self): |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigmask=34) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigmask=34) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigmask=["j"]) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigmask=["j"]) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigmask=[signal.NSIG, |
|
|
|
signal.NSIG+1]) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigmask=[signal.NSIG, |
|
|
|
signal.NSIG+1]) |
|
|
|
|
|
|
|
@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), |
|
|
|
'need signal.pthread_sigmask()') |
|
|
|
@ -1630,7 +1630,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
import signal |
|
|
|
signal.raise_signal(signal.SIGUSR1)""") |
|
|
|
try: |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', code], |
|
|
|
os.environ, |
|
|
|
@ -1646,17 +1646,17 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
|
|
|
|
def test_setsigdef_wrong_type(self): |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigdef=34) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigdef=34) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigdef=["j"]) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigdef=["j"]) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
posix.posix_spawn(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1]) |
|
|
|
self.spawn_func(sys.executable, |
|
|
|
[sys.executable, "-c", "pass"], |
|
|
|
os.environ, setsigdef=[signal.NSIG, signal.NSIG+1]) |
|
|
|
|
|
|
|
@requires_sched |
|
|
|
@unittest.skipIf(sys.platform.startswith(('freebsd', 'netbsd')), |
|
|
|
@ -1670,7 +1670,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
sys.exit(101) |
|
|
|
if os.sched_getparam(0).sched_priority != {priority}: |
|
|
|
sys.exit(102)""") |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', code], |
|
|
|
os.environ, |
|
|
|
@ -1690,7 +1690,7 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
sys.exit(101) |
|
|
|
if os.sched_getparam(0).sched_priority != {priority}: |
|
|
|
sys.exit(102)""") |
|
|
|
pid = posix.posix_spawn( |
|
|
|
pid = self.spawn_func( |
|
|
|
sys.executable, |
|
|
|
[sys.executable, '-c', code], |
|
|
|
os.environ, |
|
|
|
@ -1704,40 +1704,40 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
(os.POSIX_SPAWN_CLOSE, 0), |
|
|
|
(os.POSIX_SPAWN_DUP2, 1, 4), |
|
|
|
] |
|
|
|
pid = posix.posix_spawn(self.NOOP_PROGRAM[0], |
|
|
|
self.NOOP_PROGRAM, |
|
|
|
os.environ, |
|
|
|
file_actions=file_actions) |
|
|
|
pid = self.spawn_func(self.NOOP_PROGRAM[0], |
|
|
|
self.NOOP_PROGRAM, |
|
|
|
os.environ, |
|
|
|
file_actions=file_actions) |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
|
|
|
|
def test_bad_file_actions(self): |
|
|
|
args = self.NOOP_PROGRAM |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[None]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[None]) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[()]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[()]) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(None,)]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(None,)]) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(12345,)]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(12345,)]) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE,)]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE,)]) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE, 1, 2)]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE, 1, 2)]) |
|
|
|
with self.assertRaises(TypeError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE, None)]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE, None)]) |
|
|
|
with self.assertRaises(ValueError): |
|
|
|
posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_OPEN, |
|
|
|
3, __file__ + '\0', |
|
|
|
os.O_RDONLY, 0)]) |
|
|
|
self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_OPEN, |
|
|
|
3, __file__ + '\0', |
|
|
|
os.O_RDONLY, 0)]) |
|
|
|
|
|
|
|
def test_open_file(self): |
|
|
|
outfile = support.TESTFN |
|
|
|
@ -1752,8 +1752,8 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
stat.S_IRUSR | stat.S_IWUSR), |
|
|
|
] |
|
|
|
args = self.python_args('-c', script) |
|
|
|
pid = posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=file_actions) |
|
|
|
pid = self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=file_actions) |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
with open(outfile) as f: |
|
|
|
self.assertEqual(f.read(), 'hello') |
|
|
|
@ -1770,8 +1770,8 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
closefile.write('is closed %d' % e.errno) |
|
|
|
""" |
|
|
|
args = self.python_args('-c', script) |
|
|
|
pid = posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE, 0),]) |
|
|
|
pid = self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=[(os.POSIX_SPAWN_CLOSE, 0)]) |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
with open(closefile) as f: |
|
|
|
self.assertEqual(f.read(), 'is closed %d' % errno.EBADF) |
|
|
|
@ -1788,16 +1788,64 @@ class TestPosixSpawn(unittest.TestCase): |
|
|
|
(os.POSIX_SPAWN_DUP2, childfile.fileno(), 1), |
|
|
|
] |
|
|
|
args = self.python_args('-c', script) |
|
|
|
pid = posix.posix_spawn(args[0], args, os.environ, |
|
|
|
file_actions=file_actions) |
|
|
|
pid = self.spawn_func(args[0], args, os.environ, |
|
|
|
file_actions=file_actions) |
|
|
|
self.assertEqual(os.waitpid(pid, 0), (pid, 0)) |
|
|
|
with open(dupfile) as f: |
|
|
|
self.assertEqual(f.read(), 'hello') |
|
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(hasattr(os, 'posix_spawn'), "test needs os.posix_spawn") |
|
|
|
class TestPosixSpawn(unittest.TestCase, _PosixSpawnMixin): |
|
|
|
spawn_func = getattr(posix, 'posix_spawn', None) |
|
|
|
|
|
|
|
|
|
|
|
@unittest.skipUnless(hasattr(os, 'posix_spawnp'), "test needs os.posix_spawnp") |
|
|
|
class TestPosixSpawnP(unittest.TestCase, _PosixSpawnMixin): |
|
|
|
spawn_func = getattr(posix, 'posix_spawnp', None) |
|
|
|
|
|
|
|
@support.skip_unless_symlink |
|
|
|
def test_posix_spawnp(self): |
|
|
|
# Use a symlink to create a program in its own temporary directory |
|
|
|
temp_dir = tempfile.mkdtemp() |
|
|
|
self.addCleanup(support.rmtree, temp_dir) |
|
|
|
|
|
|
|
program = 'posix_spawnp_test_program.exe' |
|
|
|
program_fullpath = os.path.join(temp_dir, program) |
|
|
|
os.symlink(sys.executable, program_fullpath) |
|
|
|
|
|
|
|
try: |
|
|
|
path = os.pathsep.join((temp_dir, os.environ['PATH'])) |
|
|
|
except KeyError: |
|
|
|
path = temp_dir # PATH is not set |
|
|
|
|
|
|
|
spawn_args = (program, '-I', '-S', '-c', 'pass') |
|
|
|
code = textwrap.dedent(""" |
|
|
|
import os |
|
|
|
args = %a |
|
|
|
pid = os.posix_spawnp(args[0], args, os.environ) |
|
|
|
pid2, status = os.waitpid(pid, 0) |
|
|
|
if pid2 != pid: |
|
|
|
raise Exception(f"pid {pid2} != {pid}") |
|
|
|
if status != 0: |
|
|
|
raise Exception(f"status {status} != 0") |
|
|
|
""" % (spawn_args,)) |
|
|
|
|
|
|
|
# Use a subprocess to test os.posix_spawnp() with a modified PATH |
|
|
|
# environment variable: posix_spawnp() uses the current environment |
|
|
|
# to locate the program, not its environment argument. |
|
|
|
args = ('-c', code) |
|
|
|
assert_python_ok(*args, PATH=path) |
|
|
|
|
|
|
|
|
|
|
|
def test_main(): |
|
|
|
try: |
|
|
|
support.run_unittest(PosixTester, PosixGroupsTester, TestPosixSpawn) |
|
|
|
support.run_unittest( |
|
|
|
PosixTester, |
|
|
|
PosixGroupsTester, |
|
|
|
TestPosixSpawn, |
|
|
|
TestPosixSpawnP, |
|
|
|
) |
|
|
|
finally: |
|
|
|
support.reap_children() |
|
|
|
|
|
|
|
|