Repository navigation
bpo-20104: Add flag capabilities to posix_spawn #6693
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
4982abd
ad862cc
552b1dc
713d803
ecd64e4
88a831c
0fbae92
06262a5
c784e0f
514f55e
abfcd6a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
|
|
||
| import errno | ||
| import sys | ||
| import signal | ||
| import time | ||
| import os | ||
| import platform | ||
|
|
@@ -16,6 +17,7 @@ | |
| import tempfile | ||
| import unittest | ||
| import warnings | ||
| import textwrap | ||
|
|
||
| _DUMMY_SYMLINK = os.path.join(tempfile.gettempdir(), | ||
| support.TESTFN + '-dummy-symlink') | ||
|
|
@@ -1476,6 +1478,149 @@ def test_empty_file_actions(self): | |
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
| def test_resetids_explicit_default(self): | ||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', 'pass'], | ||
| os.environ, | ||
| resetids=False | ||
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too much empty lines. Use two empty lines for separating classes. And the empty line before |
||
| def test_resetids(self): | ||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', 'pass'], | ||
| os.environ, | ||
| resetids=True | ||
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
| def test_resetids_wrong_type(self): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we don't need so much similar tests. Needed only one test per error case. For example if the argument must be an iterable of integers in specified range, then test with a non-iterable, a list containing a non-integer, and a list containing an invalid integer. Your multiple tests test only the single kind of errors. |
||
| with self.assertRaises(TypeError): | ||
| posix.posix_spawn(sys.executable, | ||
| [sys.executable, "-c", "pass"], | ||
| os.environ, resetids=0) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the rationale for rejecting 0 as false? resetids=0 seems legit to me. Why not using "bool" type for this parameter? Something like:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we use I would prefer to pass only |
||
| with self.assertRaises(TypeError): | ||
| posix.posix_spawn(sys.executable, | ||
| [sys.executable, "-c", "pass"], | ||
| os.environ, resetids=None) | ||
|
|
||
| def test_setpgroup(self): | ||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', 'pass'], | ||
| os.environ, | ||
| setpgroup=os.getpgrp() | ||
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
| def test_setpgroup_wrong_type(self): | ||
| with self.assertRaises(TypeError): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reorder test in the order of performing corresponding checks in the code: first a non-iterable, then an iterable of non-integers, then out of range integers. |
||
| posix.posix_spawn(sys.executable, | ||
| [sys.executable, "-c", "pass"], | ||
| os.environ, setpgroup="023") | ||
|
|
||
| @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | ||
| 'need signal.pthread_sigmask()') | ||
| def test_setsigmask(self): | ||
| code = textwrap.dedent("""\ | ||
| import _testcapi, signal | ||
| _testcapi.raise_signal(signal.SIGUSR1)""") | ||
|
|
||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', code], | ||
| os.environ, | ||
| setsigmask=[signal.SIGUSR1] | ||
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
| def test_setsigmask_wrong_type(self): | ||
| with self.assertRaises(TypeError): | ||
| posix.posix_spawn(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"]) | ||
| with self.assertRaises(ValueError): | ||
| posix.posix_spawn(sys.executable, | ||
| [sys.executable, "-c", "pass"], | ||
| os.environ, setsigmask=[9998, 9999]) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. setsigmask or setsigdef?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would prefer a more explicit signal.NSIG rather than arbitrary integer 9999. Maybe [signal.NSIG, signal.NSIG+1]? |
||
|
|
||
| @unittest.skipUnless(hasattr(signal, 'pthread_sigmask'), | ||
| 'need signal.pthread_sigmask()') | ||
| def test_setsigdef(self): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be better if move this test closer to the setsigmask tests, above the setscheduler tests. |
||
| original_handler = signal.signal(signal.SIGUSR1, signal.SIG_IGN) | ||
| code = textwrap.dedent("""\ | ||
| import _testcapi, signal | ||
| _testcapi.raise_signal(signal.SIGUSR1)""") | ||
| try: | ||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', code], | ||
| os.environ, | ||
| setsigdef=[signal.SIGUSR1] | ||
| ) | ||
| finally: | ||
| signal.signal(signal.SIGUSR1, original_handler) | ||
|
|
||
| pid2, status = os.waitpid(pid, 0) | ||
| self.assertEqual(pid2, pid) | ||
| self.assertNotEqual(status, 0) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would suggest a stricter test:
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. done |
||
|
|
||
| def test_setsigdef_wrong_type(self): | ||
| with self.assertRaises(TypeError): | ||
| posix.posix_spawn(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"]) | ||
| with self.assertRaises(ValueError): | ||
| posix.posix_spawn(sys.executable, | ||
| [sys.executable, "-c", "pass"], | ||
| os.environ, setsigdef=[9998, 9999]) | ||
|
|
||
| @unittest.skipUnless(hasattr(posix, 'sched_setscheduler'), "can't change scheduler") | ||
| def test_setscheduler_only_param(self): | ||
| policy = os.sched_getscheduler(0) | ||
| priority = os.sched_get_priority_min(policy) | ||
| code = textwrap.dedent(f"""\ | ||
| import os | ||
| if os.sched_getscheduler(0) != {policy}: | ||
| os.exit(101) | ||
| if os.sched_getparam(0).sched_priority != {priority}: | ||
| os.exit(102)""") | ||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', code], | ||
| os.environ, | ||
| scheduler=(None, os.sched_param(priority)) | ||
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
| @unittest.skipUnless(hasattr(posix, 'sched_setscheduler'), "can't change scheduler") | ||
| def test_setscheduler_with_policy(self): | ||
| policy = os.sched_getscheduler(0) | ||
| priority = os.sched_get_priority_min(policy) | ||
| code = textwrap.dedent(f"""\ | ||
| import os | ||
| if os.sched_getscheduler(0) != {policy}: | ||
| os.exit(101) | ||
| if os.sched_getparam(0).sched_priority != {priority}: | ||
| os.exit(102)""") | ||
| pid = posix.posix_spawn( | ||
| sys.executable, | ||
| [sys.executable, '-c', code], | ||
| os.environ, | ||
| scheduler=(policy, os.sched_param(priority)) | ||
| ) | ||
| self.assertEqual(os.waitpid(pid, 0), (pid, 0)) | ||
|
|
||
| def test_multiple_file_actions(self): | ||
| file_actions = [ | ||
| (os.POSIX_SPAWN_OPEN, 3, os.path.realpath(__file__), os.O_RDONLY, 0), | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| Added support for the `setpgroup`, `resetids`, `setsigmask`, `setsigdef` and | ||
| `scheduler` parameters of `posix_spawn`. Patch by Pablo Galindo. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this
/should be here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #6725.