Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #1959 (closed defect: worksforme)

Opened 11 years ago

Last modified 8 years ago

Exceeding maximum recursion depth causes Python to crash

Reported by: igowen Owned by: anonymous
Priority: normal Milestone: 1.1.x bugfix
Component: TurboGears Version: 1.0.5
Severity: normal Keywords: crash mac osx
Cc:

Description

I ran into an odd issue with Python crashing on Mac OS X (10.5.4) with badly-written recursive function. When running the function in question in tg-admin shell, everything is fine; the appropriate RuntimeError? is generated, and a traceback is printed. However, running the development server and causing the function to be called causes Python to crash.

A simple controller function that will cause a crash:

@expose()
def crash(self):
    self.crash()

I've tested this on a Linux box, and no such crash occurs.

Attached are an image of the crash dialog and OS X's crash log.

Attachments

Python_2008-08-21-194512_Macintosh.crash Download (62.1 KB) - added by igowen 11 years ago.
Crash log
Picture 4.png Download (43.0 KB) - added by igowen 11 years ago.
screenshot of crash dialog

Change History

Changed 11 years ago by igowen

Crash log

Changed 11 years ago by igowen

screenshot of crash dialog

comment:1 Changed 11 years ago by igowen

I should also add that this is using Python 2.5.1 supplied by Apple.

comment:2 Changed 11 years ago by Chris Arndt

On Mac OS X 10.4 (Python 2.5 from python.org) this just shuts down the CherryPy process (SystemExit is raised) when I try to access the controller through the browser (i.e. http://localhost/crash). No crash dialog or log.

On Linux (Ubuntu 7.04, Python 2.5.1) this correctly raises a RuntimeError.

Maybe we should research if this due to a known Python bug on Mac OS X?

comment:3 Changed 11 years ago by Chris Arndt

  • Milestone set to 1.5

comment:4 Changed 11 years ago by igowen

10.5 exhibits the same behavior, with the addition of the crash popup.

comment:5 Changed 11 years ago by faide

Can you reproduce such a crash in a simple command line script outside the TurboGears app? If so it may be a "python on mac" problem more than a TurboGears one.

comment:6 Changed 11 years ago by igowen

I have not been able to reproduce this outside of a TurboGears application. The crash seems to occur in _d_speedups.so, which I believe is part of RuleDispatch?, so the real problem may lie with its mac build.

comment:7 Changed 11 years ago by faide

Could you then try to install RuleDispatch? by removing the speedups feature in the setup.py to see if the problem is in the speedup module of the mac compiled version?

comment:8 Changed 11 years ago by Chris Arndt

The crash also happens with the TurboGears 1.1 branch (project also quickstarted with 1.1 -> uses Genshi), so RuleDispatch is ruled out as the culprit.

comment:9 Changed 11 years ago by Chris Arndt

It seems that somehow the maximum recursion depth (MRD from now on) is not is not detected/caught properly on Mac OS X Python. The default MRD is 1000 (on all systems). If I run the tool find_recursionlimit.py from the Misc directory of the Python 2.5.2 distribution, it reports a safe MRD of 4400 on my Mac OS X 10.4.11, Python 2.5, mac mini, 2 Gb ram. Here's the last screen of output from the tool:

[...]
recurse
add
repr
init
getattr
getitem
Limit of 4300 is fine
recurse
add
repr
init
getattr
getitem
Limit of 4400 is fine
recurse
add
Segmentation fault

However, if I set the MRD with sys.setrecursionlimit() to a safe, lower number in the commands.start() function of my project, the crash does not appear when I call the /crash URL. I get the correct RuntimeError instead.

I can set the MRD as high as 632. If I set it to 633 or higher - CRASH!

It seems something in TGs internals messes with the call stack in a way that breaks the recursion limit detection. I suspect that util.call_on_stack is the culprit but this just a hunch.

Funny thing is, if I log the number of times the crash method is called before the app crashes like this:

class Root(...)
    ...
    count = 0

    @expose()
    def crash(self):
        self.count += 1
        log.debug('Count: %i', self.count)
        self.crash()

the last few lines of output I get are these:

2008-08-28 19:59:40,115 mytest2.controllers DEBUG Count: 64
2008-08-28 19:59:40,115 mytest2.controllers DEBUG Count: 64
2008-08-28 19:59:40,116 mytest2.controllers DEBUG Count: 65
2008-08-28 19:59:40,116 mytest2.controllers DEBUG Count: 65
2008-08-28 19:59:40,116 mytest2.controllers DEBUG Count: 66
2008-08-28 19:59:40,116 mytest2.controllers DEBUG Count: 66
2008-08-28 19:59:40,117 mytest2.controllers DEBUG Count: 67
2008-08-28 19:59:40,117 mytest2.controllers DEBUG Count: 67
Traceback (most recent call last):
2008-08-28 19:59:40,632 cherrypy.msg INFO ENGINE: SystemExit raised: shutting down autoreloader
2008-08-28 19:59:40,634 cherrypy.msg INFO HTTP: HTTP Server shut down
2008-08-28 19:59:40,662 cherrypy.msg INFO ENGINE: CherryPy shut down

so the crash method itself is only called 67 times. Somehow these must amount to over 4400 function calls on the stack which sneak past the max recursion protection.

comment:10 Changed 11 years ago by chrisz

On Windows XP with Py 2.4/2.5, TG 1.0/1.1, I always get an appropriate RunTimeError?.

comment:11 Changed 11 years ago by jorge.vargas

  • Keywords mac osx added

comment:12 Changed 9 years ago by chrisz

  • Milestone changed from 1.5 to 1.1.x bugfix

Can anybody using Max OS check if this is still an issue with TG 1.5 and Python version 2.6 or 2.7?

comment:13 Changed 8 years ago by chrisz

  • Status changed from new to closed
  • Resolution set to worksforme

Closing this since nobody provided further input. It's hopefully fixed in current Python/MacOS versions.

Note: See TracTickets for help on using tickets.