This issue tracker has been migrated to GitHub ,
and is currently read-only.
For more information,
see the GitHub FAQs in the Python's Developer Guide.
Created on 2008年04月04日 08:16 by theller, last changed 2022年04月11日 14:56 by admin. This issue is now closed.
| Files | ||||
|---|---|---|---|---|
| File name | Uploaded | Description | Edit | |
| excrecurse.patch | pitrou, 2008年08月30日 00:15 | |||
| Messages (18) | |||
|---|---|---|---|
| msg64920 - (view) | Author: Thomas Heller (theller) * (Python committer) | Date: 2008年04月04日 08:16 | |
[Found by Daniel Diniz (ajaksu2), see issue #2542] The following code triggers an undetected error with a debug build: """ import sys def g(): try: return g() except: return sys.exc_info() g() print 42 """ Running the code prints this: C:\svn\trunk\PCbuild>python_d test2.py 42 XXX undetected error Traceback (most recent call last): File "test2.py", line 8, in <module> print 42 RuntimeError: maximum recursion depth exceeded [8826 refs] C:\svn\trunk\PCbuild> |
|||
| msg64954 - (view) | Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) | Date: 2008年04月05日 00:34 | |
Analysis: the primary recursion error is correctly raised, but then there is a call to PyErr_NormalizeException, which calls PyEval_CallObject, which increases the stack depth and hit the recursion limit again... python2.5 don't have the problem because PyEval_CallObject did not check the recursion limit. Different solutions I can think of: - use a prebuilt exception: not possible if we still want an error message containing the context. - in PyErr_NormalizeException, "PyEval_CallObject" is too generic. We could have a special path for exception types deriving from BaseException: directly call the constructor. |
|||
| msg64961 - (view) | Author: Neal Norwitz (nnorwitz) * (Python committer) | Date: 2008年04月05日 03:05 | |
Brett, didn't you have a similar problem you fixed a while ago? I assigned to you for more input, feel free to reset to nobody. |
|||
| msg64983 - (view) | Author: Brett Cannon (brett.cannon) * (Python committer) | Date: 2008年04月05日 15:32 | |
Neal has the memory of an elephant or something. Yes, I dealt with a similar issue where the recursion limit was hit, but then normalizing the exception just caused it to hit it again. I thought I changed it such that normalizing an exception actually turned off the depth check or to raise a pre-defined exception for the recursion depth limit. I don't have time to look at this right now (still on holiday in Brussels), but if I remember correctly the last time this came up I liked the pre-allocated recursion limit exception. |
|||
| msg65053 - (view) | Author: Daniel Diniz (ajaksu2) * (Python triager) | Date: 2008年04月06日 21:22 | |
I've identified rev58032 [1] as the one introducing this issue. It's Brett's code, fixing a nasty crasher and adding a pre-built exception (PyExc_RecursionErrorInst). [1] http://svn.python.org/view?rev=58032&view=rev P.S.: Thanks Thomas for correctly identifying an issue I mis-reported :) |
|||
| msg66398 - (view) | Author: Barry A. Warsaw (barry) * (Python committer) | Date: 2008年05月08日 03:39 | |
I'm not going to hold up the 2.6 alpha release for this, but will bump it up for the first 2.6 beta. |
|||
| msg68018 - (view) | Author: Barry A. Warsaw (barry) * (Python committer) | Date: 2008年06月11日 21:15 | |
This is a bug that can be fixed after beta, so I'm knocking it back to critical for beta 1. |
|||
| msg70482 - (view) | Author: Benjamin Peterson (benjamin.peterson) * (Python committer) | Date: 2008年07月31日 02:16 | |
Ping |
|||
| msg71095 - (view) | Author: Daniel Diniz (ajaksu2) * (Python triager) | Date: 2008年08月13日 19:49 | |
FWIW, rev58032 introduced this: tstate = PyThreadState_GET(); if (++tstate->recursion_depth > Py_GetRecursionLimit()) { --tstate->recursion_depth; PyErr_SetObject(PyExc_RuntimeError, PyExc_RecursionErrorInst); return; } above this line: PyErr_NormalizeException(exc, val, tb); Contrary to (what I understand from) Amaury's analysis, ISTM that the call to PyErr_SetObject is the problem, as after the recursion limit is hit PyErr_NormalizeException isn't called again. Commenting off the PyErr_SetObject line suppresses the "undetected errors" and passes the unittests (including the infinite recursion crashers removed in that rev). I have no idea about the problems it may cause, though. |
|||
| msg71107 - (view) | Author: Brett Cannon (brett.cannon) * (Python committer) | Date: 2008年08月14日 02:36 | |
On Wed, Aug 13, 2008 at 12:49 PM, Daniel Diniz <report@bugs.python.org> wrote: > > Daniel Diniz <ajaksu@gmail.com> added the comment: > > FWIW, rev58032 introduced this: > tstate = PyThreadState_GET(); > if (++tstate->recursion_depth > Py_GetRecursionLimit()) { > --tstate->recursion_depth; > PyErr_SetObject(PyExc_RuntimeError, PyExc_RecursionErrorInst); > return; > } > above this line: > PyErr_NormalizeException(exc, val, tb); > > Contrary to (what I understand from) Amaury's analysis, ISTM that the > call to PyErr_SetObject is the problem, as after the recursion limit is > hit PyErr_NormalizeException isn't called again. > > Commenting off the PyErr_SetObject line suppresses the "undetected > errors" and passes the unittests (including the infinite recursion > crashers removed in that rev). I have no idea about the problems it may > cause, though. > If I remember correctly, that is on purpose as normalizing the exception could lead to the stack being blown again. But this totally off of memory, so I could be wrong. |
|||
| msg71651 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2008年08月21日 15:25 | |
For what it's worth, py3k has a subtler recursion checking algorithm which would probably fix this problem if backported properly. See _Py_CheckRecursiveCall() in ceval.c (lines 462+), and especially the role played by the tstate->overflowed flag, which allows a moderate overflow of the recursion count in order for error handling code to execute properly. |
|||
| msg72163 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2008年08月29日 21:53 | |
The crashers which were deleted in rev58032 should at least have been turned into unittests... well. |
|||
| msg72176 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2008年08月30日 00:05 | |
Ok, here is a patch which seems to cover all bases. It fixes the present bug, adds tests for the aforementioned ex-crashers, backports the somewhat smarter recursion checking from py3k, and improves the latter by fixing a nasty recursion bug when exceptions are ignored by C code. I have to explain the latter problem a bit. Some functions like PyDict_GetItem() are designed to silence all exceptions. If a RuntimeError is raised because of a recursion overflow, however, a flag (named "overflowed") is additionally set in the thread state structure; this flag temporarily bumps the recursion_limit by 50, so that the code which caught the exception can perform some cleanup without itself getting into the recursion limit. However, if recursion_limit + 50 is in turned reached, the interpreter aborts with a fatal error. Now, if the RuntimeError is discarded by PyDict_GetItem(), the "overflowed" flag must also be reset, because the caller won't know that there was a recursion overflow and that it must clean up. Instead, it will simply assume the requested value is not in the dict, and will continue happily... until it overflows the recursion limit again, which will trigger the aforementioned fatal error if "overflowed" has not been reset. Consequently, PyErr_Clear() now resets the "overflowed" flag if the current recursion count has gone back below the recursion limit. This improvement must also be merged back to py3k. Of course, we may also decide that all those subtle changes are not worth the risk, just to fix a few obscure glitches. |
|||
| msg72179 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2008年08月30日 00:15 | |
Ouch, there were a couple of useless lines in ceval.h. New patch. |
|||
| msg72181 - (view) | Author: Antoine Pitrou (pitrou) * (Python committer) | Date: 2008年08月30日 00:40 | |
After thinking about it a bit, I think the whole recursion checking thing has gone a bit mad. It probably deserves proper discussion on the mailing-list. In the meantime, I'm downgrading this bug to critical. |
|||
| msg101353 - (view) | Author: Sean Reifschneider (jafo) * (Python committer) | Date: 2010年03月20日 02:11 | |
The final word on this seems to be this: - Wait until when we aren't in a beta release. (DONE) - Quoting: Well, For Py3K at least we might need to consider going through the C API and fixing it so that these incorrect assumptions that functions like PyDict_GetItem() make are no longer made by introducing some new functions that behave in a "better" way. And for the recursion issue, I think it stems from corners that are cut in the C API by us. We inline functions all over the place, assume that Python's implementation underneath the hood is going to make calls that stay in C, etc. But as time has gone on and we have added flexibility to Python, more and more places have a chance to call Python code and trigger issues. from Brett's e-mail at: http://mail.python.org/pipermail/python-dev/2008-August/082107.html Anyone up to trying to make the C API changes required to get this resolved? Sean |
|||
| msg110185 - (view) | Author: Mark Lawrence (BreamoreBoy) * | Date: 2010年07月13日 13:14 | |
This has been fixed in Python 2.7, I suppose that the code could be backported to 2.6, or is it now too late so this can be closed as "won't fix"? |
|||
| msg110215 - (view) | Author: Brett Cannon (brett.cannon) * (Python committer) | Date: 2010年07月13日 18:50 | |
It theoretically could be backported so it can stay open for now if someone feels adventurous to backport before 2.6.6. Once that's out the door, though, this can get closed. |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022年04月11日 14:56:33 | admin | set | github: 46800 |
| 2010年08月16日 21:38:15 | BreamoreBoy | set | status: open -> closed resolution: wont fix |
| 2010年07月13日 18:50:56 | brett.cannon | set | messages: + msg110215 |
| 2010年07月13日 13:14:12 | BreamoreBoy | set | nosy:
+ BreamoreBoy messages: + msg110185 |
| 2010年03月20日 02:11:48 | jafo | set | nosy:
+ jafo messages: + msg101353 |
| 2008年08月30日 00:40:02 | pitrou | set | priority: release blocker -> critical messages: + msg72181 |
| 2008年08月30日 00:15:13 | pitrou | set | files:
+ excrecurse.patch messages: + msg72179 |
| 2008年08月30日 00:14:33 | pitrou | set | files: - excrecurse.patch |
| 2008年08月30日 00:05:58 | pitrou | set | keywords: + needs review |
| 2008年08月30日 00:05:45 | pitrou | set | files:
+ excrecurse.patch keywords: + patch messages: + msg72176 |
| 2008年08月29日 21:53:47 | pitrou | set | messages: + msg72163 |
| 2008年08月21日 15:25:21 | pitrou | set | nosy:
+ pitrou messages: + msg71651 |
| 2008年08月21日 14:24:49 | benjamin.peterson | set | priority: critical -> release blocker |
| 2008年08月14日 02:36:43 | brett.cannon | set | messages: + msg71107 |
| 2008年08月13日 19:49:34 | ajaksu2 | set | messages: + msg71095 |
| 2008年07月31日 02:16:26 | benjamin.peterson | set | nosy:
+ benjamin.peterson messages: + msg70482 |
| 2008年06月11日 21:15:44 | barry | set | priority: release blocker -> critical messages: + msg68018 |
| 2008年05月13日 08:38:44 | georg.brandl | set | priority: critical -> release blocker |
| 2008年05月08日 03:39:35 | barry | set | priority: release blocker -> critical nosy: + barry messages: + msg66398 |
| 2008年04月06日 21:22:38 | ajaksu2 | set | messages: + msg65053 |
| 2008年04月05日 15:32:02 | brett.cannon | set | assignee: brett.cannon -> messages: + msg64983 |
| 2008年04月05日 04:02:48 | ajaksu2 | set | nosy: + ajaksu2 |
| 2008年04月05日 03:05:04 | nnorwitz | set | priority: release blocker assignee: brett.cannon messages: + msg64961 nosy: + brett.cannon, nnorwitz |
| 2008年04月05日 00:34:24 | amaury.forgeotdarc | set | nosy:
+ amaury.forgeotdarc messages: + msg64954 |
| 2008年04月04日 08:16:41 | theller | create | |