You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
test_multiprocessing_fork: test_semaphore_tracker_sigint() fails with -W error #77794
test_semaphore_tracker_sigint() emits a warning. If the test is run with -W error, the test fails.
vstinner@apu$ ./python -m test test_multiprocessing_fork -v -m test_semaphore_tracker_sigint
(...)
test_semaphore_tracker_sigint (test.test_multiprocessing_fork.TestSemaphoreTracker) ... /home/vstinner/prog/python/master/Lib/multiprocessing/semaphore_tracker.py:55: UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
warnings.warn('semaphore_tracker: process died unexpectedly, '
ok
(...)
Tests result: SUCCESS
Traceback (most recent call last):
File "/home/vstinner/prog/python/master/Lib/test/_test_multiprocessing.py", line 4533, in test_semaphore_tracker_sigintself.check_semaphore_tracker_death(signal.SIGINT, False)
File "/home/vstinner/prog/python/master/Lib/test/_test_multiprocessing.py", line 4521, in check_semaphore_tracker_death
sem = ctx.Semaphore()
File "/home/vstinner/prog/python/master/Lib/multiprocessing/context.py", line 82, in Semaphorereturn Semaphore(value, ctx=self.get_context())
File "/home/vstinner/prog/python/master/Lib/multiprocessing/synchronize.py", line 127, in __init__
SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX, ctx=ctx)
File "/home/vstinner/prog/python/master/Lib/multiprocessing/synchronize.py", line 81, in __init__
register(self._semlock.name)
File "/home/vstinner/prog/python/master/Lib/multiprocessing/semaphore_tracker.py", line 83, in registerself._send('REGISTER', name)
File "/home/vstinner/prog/python/master/Lib/multiprocessing/semaphore_tracker.py", line 90, in _sendself.ensure_running()
File "/home/vstinner/prog/python/master/Lib/multiprocessing/semaphore_tracker.py", line 55, in ensure_running
warnings.warn('semaphore_tracker: process died unexpectedly, 'UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
(...)
Tests result: FAILURE
There are two problems in test_semaphore_tracker_sigint. One of the problems is that if should_die is False, the code does not check
that no warning is raised (and the warning is being raised, so this
the error has pass silently.) The other problem is a race condition
between the parent calls _semaphore_tracker.ensure_running() (which in turn spawns the semaphore_tracker using _posixsubprocess.fork_exec) and the child registering the signals. So basically, the parent sends the signal before the child protects against the signal. Modifying:
_semaphore_tracker.ensure_running()
pid=_semaphore_tracker._pidos.kill(pid, signum)
time.sleep(1.0) # give it time to die
to
_semaphore_tracker.ensure_running()
pid=_semaphore_tracker._pidtime.sleep(1.0) # Give time for the child to register the signal handlersos.kill(pid, signum)
time.sleep(1.0) # give it time to die
fix the issue. I have tested this on one of the most grumpy and slow buildbots (gcc110) and it works.
I cannot think of a different way of waiting for the child to register the signals without modifying the child code for testing so I am not sure that we can do anything rather than the sleep.
You can know that the semaphore tracker is running by sending it an invalid command and seeing the error written to stderr. The semaphore tracker either inherits sys.stderr from the parent process (if possible) or uses its own. This is a bit of a hack, but might be worth it to avoid another wasted second on every run of the test suite.
Additionally, as I commented in the PR, apart from the race condition I think the test should be modified so it fails if the warning is raised and not expected:
The problem is that the test was silently failing when SIGINT was >being delivered as the test does not check that no warnings are >raised. Notice that the presence of a warning means that the process >died and therefore SIGINT did kill the process, which is precisely >what the test checks that does not happen.
I think in order to check that the test works as intended without the >need to run the suite with -Wall, we need to modify the test.
If buildbots hurt, I suggest skipping the tests on the buildbots.
Let's do that. Pablo: do you want to write a PR to always skip TestSemaphoreTracker with a reference to this issue? Example: skipIf(True, "bpo-33613: the test has a race condition").
There is no easy wait to only skip a test on buildbots.
They work fine otherwise.
The race condition impacts everyone. It's just less likely if your computer is fast enough. The bug is much more likely if you "force" the bad path:
diff --git a/Lib/multiprocessing/semaphore_tracker.py b/Lib/multiprocessing/semaphore_tracker.py
index 3b50a46ddc..7261b43725 100644
--- a/Lib/multiprocessing/semaphore_tracker.py+++ b/Lib/multiprocessing/semaphore_tracker.py@@ -107,6 +107,8 @@ getfd = _semaphore_tracker.getfd
def main(fd):
'''Run semaphore tracker.'''
# protect the process from ^C and "killall python" etc
+ import time+ time.sleep(0.5)
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py
index 5c625dd495..6f9f7583e2 100644
--- a/Lib/test/_test_multiprocessing.py+++ b/Lib/test/_test_multiprocessing.py@@ -4193,7 +4193,6 @@ class TestSemaphoreTracker(unittest.TestCase):
_multiprocessing.sem_unlink(name1)
p.terminate()
p.wait()
- time.sleep(2.0)
with self.assertRaises(OSError) as ctx:
_multiprocessing.sem_unlink(name2)
# docs say it should be ENOENT, but OSX seems to give EINVAL
By the way, "no user-visible bug is fixed here": I agree that it's not easy to trigger manually the bug (when pressing CTRL+C), but I don't see why an user couldn't hit this bug. The race condition is now obvious to me.
I don't want to spend hours arguing. This issue is sufficiently rare and unlikely in normal conditions that I don't think we should risk regressions by trying to fix it.
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4562, in test_semaphore_tracker_sigkillself.check_semaphore_tracker_death(signal.SIGKILL, True)
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4526, in check_semaphore_tracker_death
_semaphore_tracker.ensure_running()
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 64, in ensure_running
warnings.warn('semaphore_tracker: process died unexpectedly, 'UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4554, in test_semaphore_tracker_sigintself.check_semaphore_tracker_death(signal.SIGINT, False)
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4526, in check_semaphore_tracker_death
_semaphore_tracker.ensure_running()
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 64, in ensure_running
warnings.warn('semaphore_tracker: process died unexpectedly, 'UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4562, in test_semaphore_tracker_sigkillself.check_semaphore_tracker_death(signal.SIGKILL, True)
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4534, in check_semaphore_tracker_death
sem = ctx.Semaphore()
File "/home/serhiy/py/cpython/Lib/multiprocessing/context.py", line 82, in Semaphorereturn Semaphore(value, ctx=self.get_context())
File "/home/serhiy/py/cpython/Lib/multiprocessing/synchronize.py", line 126, in __init__
SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX, ctx=ctx)
File "/home/serhiy/py/cpython/Lib/multiprocessing/synchronize.py", line 80, in __init__
register(self._semlock.name)
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 104, in registerself._send('REGISTER', name)
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 111, in _sendself.ensure_running()
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 64, in ensure_running
warnings.warn('semaphore_tracker: process died unexpectedly, 'UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4554, in test_semaphore_tracker_sigintself.check_semaphore_tracker_death(signal.SIGINT, False)
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4526, in check_semaphore_tracker_death
_semaphore_tracker.ensure_running()
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 64, in ensure_running
warnings.warn('semaphore_tracker: process died unexpectedly, 'UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
Traceback (most recent call last):
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4562, in test_semaphore_tracker_sigkillself.check_semaphore_tracker_death(signal.SIGKILL, True)
File "/home/serhiy/py/cpython/Lib/test/_test_multiprocessing.py", line 4534, in check_semaphore_tracker_death
sem = ctx.Semaphore()
File "/home/serhiy/py/cpython/Lib/multiprocessing/context.py", line 82, in Semaphorereturn Semaphore(value, ctx=self.get_context())
File "/home/serhiy/py/cpython/Lib/multiprocessing/synchronize.py", line 126, in __init__
SemLock.__init__(self, SEMAPHORE, value, SEM_VALUE_MAX, ctx=ctx)
File "/home/serhiy/py/cpython/Lib/multiprocessing/synchronize.py", line 80, in __init__
register(self._semlock.name)
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 104, in registerself._send('REGISTER', name)
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 111, in _sendself.ensure_running()
File "/home/serhiy/py/cpython/Lib/multiprocessing/semaphore_tracker.py", line 64, in ensure_running
warnings.warn('semaphore_tracker: process died unexpectedly, 'UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
Activity
vstinner commentedon May 23, 2018
test_semaphore_tracker_sigint() emits a warning. If the test is run with -W error, the test fails.
vstinner@apu$ ./python -m test test_multiprocessing_fork -v -m test_semaphore_tracker_sigint
(...)
test_semaphore_tracker_sigint (test.test_multiprocessing_fork.TestSemaphoreTracker) ... /home/vstinner/prog/python/master/Lib/multiprocessing/semaphore_tracker.py:55: UserWarning: semaphore_tracker: process died unexpectedly, relaunching. Some semaphores might leak.
warnings.warn('semaphore_tracker: process died unexpectedly, '
ok
(...)
Tests result: SUCCESS
vstinner@apu$ ./python -Werror -m test test_multiprocessing_fork -v -m test_semaphore_tracker_sigint
(...)
======================================================================
ERROR: test_semaphore_tracker_sigint (test.test_multiprocessing_fork.TestSemaphoreTracker)
----------------------------------------------------------------------
vstinner commentedon May 23, 2018
Note: I found this bug while working on bpo-33612.
vstinner commentedon May 23, 2018
(Oops, I attached a file and added two comments to this issue, whereas I wanted to comment bpo-33612.)
serhiy-storchaka commentedon May 23, 2018
See also some information about this in bpo-31463.
pablogsal commentedon Jun 20, 2018
I would like to work on this issue and on bpo-31463
vstinner commentedon Jun 20, 2018
Say it on bpo-31463 as well on that case ;-)
pablogsal commentedon Jun 20, 2018
There are two problems in test_semaphore_tracker_sigint. One of the problems is that if
should_dieis False, the code does not checkthat no warning is raised (and the warning is being raised, so this
the error has pass silently.) The other problem is a race condition
between the parent calls
_semaphore_tracker.ensure_running()(which in turn spawns the semaphore_tracker using_posixsubprocess.fork_exec) and the child registering the signals. So basically, the parent sends the signal before the child protects against the signal. Modifying:to
fix the issue. I have tested this on one of the most grumpy and slow buildbots (gcc110) and it works.
I cannot think of a different way of waiting for the child to register the signals without modifying the child code for testing so I am not sure that we can do anything rather than the sleep.
taleinat commentedon Jun 24, 2018
You can know that the semaphore tracker is running by sending it an invalid command and seeing the error written to stderr. The semaphore tracker either inherits sys.stderr from the parent process (if possible) or uses its own. This is a bit of a hack, but might be worth it to avoid another wasted second on every run of the test suite.
pablogsal commentedon Jun 24, 2018
@taleinat Sadly, if the semaphore_tracker receives an invalid command, it raises and dies, making the test impossible:
pitrou commentedon Jun 24, 2018
We can easily add a 'NOOP' command to the semaphore tracker if it helps solve that issue.
pablogsal commentedon Jun 24, 2018
Sorry, I was wrong, it does not die. I am investigating this solution using stderr.
pablogsal commentedon Jun 24, 2018
Additionally, as I commented in the PR, apart from the race condition I think the test should be modified so it fails if the warning is raised and not expected:
10 remaining items
pitrou commentedon Sep 4, 2018
As I wrote on Github: no user-visible bug is fixed here, and we shouldn't risk introducing regressions by backporting those changes.
If buildbots hurt, I suggest skipping the tests on the buildbots.
vstinner commentedon Sep 4, 2018
Let's do that. Pablo: do you want to write a PR to always skip TestSemaphoreTracker with a reference to this issue? Example: skipIf(True, "bpo-33613: the test has a race condition").
pitrou commentedon Sep 4, 2018
Please only skip those tests on buildbots. They work fine otherwise.
vstinner commentedon Sep 4, 2018
There is no easy wait to only skip a test on buildbots.
The race condition impacts everyone. It's just less likely if your computer is fast enough. The bug is much more likely if you "force" the bad path:
pitrou commentedon Sep 4, 2018
Le 04/09/2018 à 11:16, STINNER Victor a écrit :
Which bug? It's only a failing test.
vstinner commentedon Sep 4, 2018
By the way, "no user-visible bug is fixed here": I agree that it's not easy to trigger manually the bug (when pressing CTRL+C), but I don't see why an user couldn't hit this bug. The race condition is now obvious to me.
pitrou commentedon Sep 4, 2018
I don't want to spend hours arguing. This issue is sufficiently rare and unlikely in normal conditions that I don't think we should risk regressions by trying to fix it.
vstinner commentedon Sep 4, 2018
Linux vendors run the full test suite. If the test suite fails, the build of the package fails as well. It's annoying.
serhiy-storchaka commentedon Oct 6, 2018
After this change tests are failed when ran with -Werror.
======================================================================
ERROR: test_semaphore_tracker_sigkill (test.test_multiprocessing_fork.TestSemaphoreTracker)
----------------------------------------------------------------------
...
======================================================================
ERROR: test_semaphore_tracker_sigint (test.test_multiprocessing_forkserver.TestSemaphoreTracker)
----------------------------------------------------------------------
======================================================================
ERROR: test_semaphore_tracker_sigkill (test.test_multiprocessing_forkserver.TestSemaphoreTracker)
----------------------------------------------------------------------
...
======================================================================
ERROR: test_semaphore_tracker_sigint (test.test_multiprocessing_spawn.TestSemaphoreTracker)
----------------------------------------------------------------------
======================================================================
ERROR: test_semaphore_tracker_sigkill (test.test_multiprocessing_spawn.TestSemaphoreTracker)
----------------------------------------------------------------------
And I'm puzzled by the line
pablogsal commentedon Oct 10, 2018
New changeset 3058b7d by Pablo Galindo in branch 'master':
bpo-33613: Fix test_semaphore_tracker signal tests when using -Werror (GH-9778)
3058b7d