sys.exit() as a Sequence Function throws Exception

Hi all,

Simply put, when I use sys.exit() as a Sequence function, python throws an exception.

import sys
import atexit

from direct.showbase.ShowBase import ShowBase
from direct.interval.IntervalGlobal import *

class MyClass(ShowBase):
 
    def __init__(self):
		ShowBase.__init__(self)
		atexit.register(self.exitfunc)
		self.sequence = Sequence(name="seq")
		self.sequence.append(Wait(2.0))
		self.sequence.append(Func(sys.exit))
		self.sequence.start()

if __name__ == "__main__":
    
	obj = MyClass()
	obj.run()

I can somehow sense what might be causing the problem but is this an expected behavior?

Thank you,
UB

What kind of exception? Could you post it here?

Here it is:

Indeed it does, sys.exit() actually works by raising the exception SystemExit. The low-level C++ interval handler detects this exception and reports it. This is arguably a mistake, but that’s what’s going on.

It’s probably better to call base.userExit() if you want to exit anyway.

David

Thank you David. I will use your recommendation.

UP

base.userExit() also throws an exception in the same context (probably using sys.exit() at some point).

It is not a catastrophic event but I just wanted it to be on record.

UB

Yep. From [color=darkred]ShowBase.py:

    def userExit(self):
        # The user has requested we exit the program.  Deal with this.
        if self.exitFunc:
            self.exitFunc()
        self.notify.info("Exiting ShowBase.")
        self.finalizeExit()

    def finalizeExit(self):
        sys.exit()

Try os._exit(0)

Well, that might not be such a great solution, because it doesn’t give Panda a chance to clean itself up gracefully before it exits, which can cause problems on some platforms.

Really, for now, the best solution is not to call this exit function from within an interval, but to use some other mechanism to trigger an exit condition, such as an event. For instance, you can hang a hook on the message “exit” that calls base.userExit(), and then put messenger.send(‘exit’) in your interval.

I’ll put in a special-case handler for SystemExit in the interval manager for the future.

David

I found that using messenger.send() triggered the same exception. Further investigation revealed that messenger.send() immediately called the corresponding accept handler (hooked to sys.exit), not a delayed until end of frame call or anything.

I used this work-around:

def	myexit():
	taskMgr.add(sys.exit, "sys.exit")

# and of course, add the interval:

	 FunctionInterval(myexit),

Works like buttah! Thanks
Kurt