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
Regression caused by CALL_FUNCTION specialization for C function calls (test_urllib fails when run multiple times) #90623
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee=Noneclosed_at=Nonecreated_at=<Date2022-01-22.01:30:09.079>labels= ['release-blocker', 'tests', '3.11']
title='Regression caused by CALL_FUNCTION specialization for C function calls (test_urllib fails when run multiple times)'updated_at=<Date2022-02-18.11:00:24.942>user='https://github.com/vstinner'
test_unittest: TestBreakSignalDefault.testInstallHandler() fails if run after TestBreak:
---------
$ ./python -m test -v test_unittest -R 3:3 -m '*TestBreak.testHandlerReplacedButCalled' -m '*TestBreak.testInstallHandler' -m '*TestBreakSignalDefault.testInstallHandler'
(...)
beginning 6 repetitions
123456
testHandlerReplacedButCalled (unittest.test.test_break.TestBreak) ... ok
testInstallHandler (unittest.test.test_break.TestBreak) ... ok
testInstallHandler (unittest.test.test_break.TestBreakSignalDefault) ... ok
Ran 3 tests in 0.003s
OK
(...)
.testHandlerReplacedButCalled (unittest.test.test_break.TestBreak) ... ok
testInstallHandler (unittest.test.test_break.TestBreak) ... ok
testInstallHandler (unittest.test.test_break.TestBreakSignalDefault) ... FAIL
Traceback (most recent call last):
File "/home/vstinner/python/main/Lib/unittest/test/test_break.py", line 38, in testInstallHandlerself.assertTrue(unittest.signals._interrupt_handler.called)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^AssertionError: False is not true
(...)
Or you can use a "bisect" file:
---
unittest.test.test_break.TestBreak.testHandlerReplacedButCalled
unittest.test.test_break.TestBreak.testInstallHandler
unittest.test.test_break.TestBreakSignalDefault.testInstallHandler
---
And the command:
./python -m test -v -F test_unittest --matchfile=bisect
Or the command:
./python -m test -v test_unittest -R 3:3 --matchfile=bisect
changed the title [-]test_unittest: TestBreakSignalDefault.testInstallHandler() fails if run after TestBreak[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls[/+]on Jan 22, 2022
changed the title [-]test_unittest: TestBreakSignalDefault.testInstallHandler() fails if run after TestBreak[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls[/+]on Jan 22, 2022
The problem is that the optimization no longer checks for pending signals in TARGET(CALL_NO_KW_BUILTIN_FAST). The patch below fix my issue. I guess that other opcode needs an additional CHECK_EVAL_BREAKER().
No, it isn't. The interpreter checks the eval breaker frequently enough. It checks on all back edges and on all calls to Python functions.
The test probably needs to be fixed, or extended. It is signals sent from another process or thread that we should be testing for.
I'm happy to merge PR 30826, but if you are really concerned about prompt delivery of signals, then you should be worried about C extensions.
If you are worried about being able to interrupt programs, then you also
worry about poorly written Python code that uses `except:`.
Regarding C extensions, I think clear documentation that extension authors need to check for signals in any code that might run for a few hundred microseconds or longer is the best approach.
For `except:`, maybe we could issue a syntax warning, as `except:` is universally considered to be bad practice.
Regarding C extensions, I think clear documentation that extension authors need to check for signals in any code that might run for a few hundred microseconds or longer is the best approach.
Python 3.10 doesn't require it. If you want to change Python 3.11 behavior, please announce the change on python-dev and capi-sig mailing lists, and document it carefully in What's New in Python 3.11.
I'm not talking about checking frequently interruptions while a function is running, I'm only talking about the "end" of a C function (exit). In Python 3.10, ceval.c does it automatically.
changed the title [-]Regression caused by CALL_FUNCTION specialization for C function calls[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls (test_urllib fails when run multiple times)[/+]on Feb 11, 2022
changed the title [-]Regression caused by CALL_FUNCTION specialization for C function calls[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls (test_urllib fails when run multiple times)[/+]on Feb 11, 2022
I confirm that attached bug.py script no longer fails on the current main branch.
Moreover, #90623 (comment) test no longer fails: I ran ./python -m test -v -F test_unittest --matchfile=bisect for 256 iterations (1 minute), it didn't fail.
Activity
vstinner commentedon Jan 22, 2022
test_unittest: TestBreakSignalDefault.testInstallHandler() fails if run after TestBreak:
---------
Ran 3 tests in 0.003s
OK
(...)
.testHandlerReplacedButCalled (unittest.test.test_break.TestBreak) ... ok
testInstallHandler (unittest.test.test_break.TestBreak) ... ok
testInstallHandler (unittest.test.test_break.TestBreakSignalDefault) ... FAIL
======================================================================
FAIL: testInstallHandler (unittest.test.test_break.TestBreakSignalDefault)
----------------------------------------------------------------------
Or you can use a "bisect" file:
---
unittest.test.test_break.TestBreak.testHandlerReplacedButCalled
unittest.test.test_break.TestBreak.testInstallHandler
unittest.test.test_break.TestBreakSignalDefault.testInstallHandler
---
And the command:
./python -m test -v -F test_unittest --matchfile=bisect
Or the command:
./python -m test -v test_unittest -R 3:3 --matchfile=bisect
It fails starting at the 4th iteration.
vstinner commentedon Jan 22, 2022
It's a regression introduced by the following change:
commit 3163e68
Author: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Date: Wed Oct 20 07:16:36 2021 +0800
vstinner commentedon Jan 22, 2022
Attached bug.py reproduces the bug without unittest, just run:
./python bug.py
On Python 3.10, it writes:
---
LOOP 0
LOOP 1
(...)
LOOP 14
LOOP 15
---
On the main branch, it fails with:
---
gvanrossum commentedon Jan 22, 2022
@kj, are you looking into this?
[-]test_unittest: TestBreakSignalDefault.testInstallHandler() fails if run after TestBreak[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls[/+][-]test_unittest: TestBreakSignalDefault.testInstallHandler() fails if run after TestBreak[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls[/+]vstinner commentedon Jan 23, 2022
The problem is that the optimization no longer checks for pending signals in TARGET(CALL_NO_KW_BUILTIN_FAST). The patch below fix my issue. I guess that other opcode needs an additional CHECK_EVAL_BREAKER().
vstinner commentedon Jan 23, 2022
It seems like the following target miss CHECK_EVAL_BREAKER():
CHECK_EVAL_BREAKER() matters for signals, but also multithreading (drop the GIL), asynchronous exception and pending calls.
Fidget-Spinner commentedon Jan 23, 2022
Thanks @victor for catching this and figuring it out. I had a hard time narrowing this down since I'm on Windows which doesn't support signals :(.
I'll handle the required patch and tests.
4 remaining items
vstinner commentedon Jan 23, 2022
See my previous comment: "CHECK_EVAL_BREAKER() matters for signals, but also multithreading (drop the GIL), asynchronous exception and pending calls."
If a thread executes a function which only uses opcodes which don't call CHECK_EVAL_BREAKER(), I understand that it can eat more than its slice of 5 ms, see sys.getswitchinterval():
https://docs.python.org/dev/library/sys.html#sys.getswitchinterval
So it's also a threads scheduling issue, no?
markshannon commentedon Jan 24, 2022
No, it isn't. The interpreter checks the eval breaker frequently enough. It checks on all back edges and on all calls to Python functions.
The test probably needs to be fixed, or extended. It is signals sent from another process or thread that we should be testing for.
I'm happy to merge PR 30826, but if you are really concerned about prompt delivery of signals, then you should be worried about C extensions.
If you are worried about being able to interrupt programs, then you also
worry about poorly written Python code that uses `except:`.
Regarding C extensions, I think clear documentation that extension authors need to check for signals in any code that might run for a few hundred microseconds or longer is the best approach.
For `except:`, maybe we could issue a syntax warning, as `except:` is universally considered to be bad practice.
vstinner commentedon Jan 25, 2022
Python 3.10 doesn't require it. If you want to change Python 3.11 behavior, please announce the change on python-dev and capi-sig mailing lists, and document it carefully in What's New in Python 3.11.
I'm not talking about checking frequently interruptions while a function is running, I'm only talking about the "end" of a C function (exit). In Python 3.10, ceval.c does it automatically.
[-]Regression caused by CALL_FUNCTION specialization for C function calls[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls (test_urllib fails when run multiple times)[/+][-]Regression caused by CALL_FUNCTION specialization for C function calls[/-][+]Regression caused by CALL_FUNCTION specialization for C function calls (test_urllib fails when run multiple times)[/+]Fidget-Spinner commentedon Apr 20, 2022
@vstinner this bug is fixed after #31404 right? Can this be closed?
vstinner commentedon Apr 20, 2022
I wanted to enhance signal.raise_signal(), here is my new PR: #91756
vstinner commentedon Apr 20, 2022
I confirm that attached bug.py script no longer fails on the current main branch.
Moreover, #90623 (comment) test no longer fails: I ran
./python -m test -v -F test_unittest --matchfile=bisectfor 256 iterations (1 minute), it didn't fail.gh-90623: signal.raise_signal() calls PyErr_CheckSignals() (#91756)
vstinner commentedon Apr 21, 2022
Merged. I close the issue. Thanks for the ceval.c fix!