Title: RuntimeError: settrace/setprofile function gets lost
Type: behavior Stage:
Components: Versions: Python 3.8, Python 3.7
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: BTaskaya, arigo, gphemsley, vstinner
Priority: normal Keywords:

Created on 2014-12-08 14:26 by arigo, last changed 2019-05-19 06:40 by BTaskaya.

File name Uploaded Description Edit arigo, 2014-12-08 14:26
Messages (2)
msg232305 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2014-12-08 14:26
It's not possible to write a settrace() or setprofile() function that remains active if we're about to run out of stack. If we are, we get a RuntimeError when the function is called. The RuntimeError is normally propagated, but in case it is eaten (e.g. see example) then the program continues to run normally --- but the trace/profile function is disabled from now on.
msg342835 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python committer) Date: 2019-05-19 06:40
I try to track down this. 

sys_settrace calls PyEval_SetTrace with trace_trampoline and the function given to it. The trace_trampoline is important because it checks the result and if result is NULL (for example like f() recursion in your code) it sets c_tracefunc and c_traceobj to NULL. It is why it doesnt work.

if (result == NULL) {
    PyEval_SetTrace(NULL, NULL);
    return -1;

We can create a simple reset function for resetting everything and then setting c_tracefunc, c_traceobj variables back to the thread state.

But then a set of tests will fail with raw ValueError produced by tracer.

class RaisingTraceFuncTestCase(unittest.TestCase):

    def trace(self, frame, event, arg):
        """A trace function that raises an exception in response to a
        specific trace event."""
        if event == self.raiseOnEvent:
            raise ValueError # just something that isn't RuntimeError
            return self.trace

This should be catched in
    def run_test_for_event(self, event):
            for i in range(sys.getrecursionlimit() + 1):
                except ValueError:
          "exception not raised!")
        except RuntimeError:
  "recursion counter not reset")

but after resetting, it doesn't work. I'm missing something but i dont know what i'm missing.
Date User Action Args
2019-05-19 06:40:30BTaskayasetmessages: + msg342835
2019-05-19 06:13:46BTaskayasetversions: + Python 3.7, Python 3.8
2019-05-19 06:13:12BTaskayasetnosy: + BTaskaya
2019-05-18 01:26:54gphemsleysetnosy: + gphemsley
2014-12-08 14:29:37vstinnersetnosy: + vstinner
2014-12-08 14:26:18arigocreate