[SOLVED] Python keeps running after closing panda

On my new system, the Python process won’t stop after closing the window spawned by panda.

The only way to stop python.exe is to close it from the task manager.

I’ve tried some of the samples, like the carousel / asteroids and getting the same issue.

Using Windows 8 i386 build 597

In fact, even sys.exit doesn’t seem to do anything when fired from an event.

A simple example:

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
import sys


class World(DirectObject):
  def __init__(self):

  	self.accept('escape', self.exit)

  	# Check to make sure keyboard events working
  	messenger.toggleVerbose()

  	print 'Started'

  	#This works
  	#sys.exit()

  def exit(self):
  	print 'Exiting'
  	sys.exit()
  	print 'After exit'

w = World()
run()

Output:

Started
:Messenger(debug): sent event: resetClock sentArgs = [-0.015849385041402098], taskChain = None
:Messenger(debug): sent event: window-event sentArgs = [<panda3d.core.GraphicsWindow object at 0x02E36608>], taskChain = None
:Messenger(debug): sent event: aspectRatioChanged sentArgs = [], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask resetPrevTransform], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask dataLoop], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask ivalLoop], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask collisionLoop], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask garbageCollectStates], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask igLoop], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask audioLoop], taskChain = None
:Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask eventManager], taskChain = None
:Messenger(debug): sent event: mouse1 sentArgs = [], taskChain = None
:Messenger(debug): sent event: time-mouse1 sentArgs = [1.2402593753895987], taskChain = None
:Messenger(debug): sent event: mousedev1-mouse1 sentArgs = [], taskChain = None
:Messenger(debug): sent event: mouse1-up sentArgs = [], taskChain = None
:Messenger(debug): sent event: time-mouse1-up sentArgs = [1.3079306714880812], taskChain = None
:Messenger(debug): sent event: mousedev1-mouse1-up sentArgs = [], taskChain = None
:Messenger(debug): sent event: escape sentArgs = [], taskChain = None
Exiting

After pressing escape, no other events are generated by keyboard/mouse, although the window is still open.

Once I force stopped the process, the window closes and “[Finished in …]” message appeared in my console.

This is a known bug in the development builds that we haven’t figured out yet. Any help figuring out the cause would be appreciated.

There were some bugs, I’ve created a new ShowBase.py based on rdb’s patches, you can find it here:
pastebin.com/WBkh56kc

Now run() returns after the window got closed

You also have to add this two lines below “while self.running:” in direct/task/Task.py-run():

if base.win is None or base.win.getGsg() is None:
    return

Do you know which exact development build it first appeared in? If not, would this be helpful information?

I think it was introduced with rdb’s changes to interrogate

Many thanks to tobspr for the fixes!

I’m not sure which change caused it, though tobspr’s suggestion is a good one. Yeah, it would be useful to know, since we may have accidentally caused some sort of low-level bug somewhere.

What seems to be this bug shows up for me on windows 7 as well, starting some time after i386 development build #555, from back in June. I would be happy to test out some builds between now and then to isolate its first appearance.

What date were they committed?

I think either this commit: github.com/panda3d/incremental/ … b9ce4cd9de

Or some commit near to this one

Good call. Just tested and found the bug first appears in nightly build #583. Build #582 (which is bug free) came out on the 15th of July and #583 came out on the 23rd of July. The interrogate overhaul commit lands between those two dates.

Excellent detective work guys, thanks a lot. Sadly, even knowing this, it’s hard to figure out in which part of the code it is specifically going wrong. I changed many things in my interrogate commit that effect pretty much every Python method out there.

My best guess is that a reference count is not being managed properly somewhere, causing a memory leak. If I had to guess, it’d be somewhere in the task system, where we pass PyObject pointers to the PythonTask object, and a part of the new wrapper code might not be decrementing the reference count properly.

I’ll continue to investigate. If anyone has any leads on which methods or classes might be affected, please let me know.

I am not sure if this helps, but whenever sys.exit() is called and the bug locks things up, I get a number of error messages like these:

C:\Panda3D-1.9.0\direct\showbase\Audio3DManager.py:258: RuntimeWarning: tp_compare didn't return -1 or -2 for exception
    if self.audio_manager.getActive()==0:
c:\sim\physics.py:135: RuntimeWarning: tp_compare didn't return -1 or -2 for exception
    if body.is_live() == False:

All errors regard if statements like shown.

Hmm, very odd. I didn’t actually change anything about our tp_compare, so this must be indicating some lower-level error somewhere. Bah. I’ll keep looking.

I get something similar, although not quite:

This is after I fire an exception to stop run().

If I call taskMgr.step() myself in a loop, everything works fine.

Heres what I have so far with inline comments on what I’ve tried, not sure if it helps:

from pandac.PandaModules import loadPrcFileData
'''
loadPrcFileData('', 'notify-level debug')
loadPrcFileData('', 'default-directnotify-level warning')
'''

import direct.directbase.DirectStart
from pandac.PandaModules import *
from direct.showbase.DirectObject import DirectObject
import sys




class World(DirectObject):
  def __init__(self):

    #PStatClient.connect()

    self.accept('escape', self.exit)

    # Check to make sure keyboard events working
    messenger.toggleVerbose()

    print 'Started'

    self.keepGoing = True

    #This works
    #sys.exit()

    # Handling the step ourselves works
    '''
    while(self.keepGoing):
      taskMgr.step()
    '''
    

  def exit(self):

    print 'Exiting'

    # Stop the main loop
    self.keepGoing = False

    
    # Cleaning up some sticky tasks don't seem to help
    '''
    taskMgr.remove('eventManager')
    taskMgr.remove('audioLoop')
    taskMgr.remove('dataLoop')    
    '''

    print base.taskMgr

    # Either of these causes some weird stuff to happen
    #raise KeyboardInterrupt
    #raise Exception

    # This works
    #taskMgr.stop()

    # Or this
    #base.exitfunc()    

    # Or even this
    #base.taskMgr.running = False

    sys.exit()

    print 'After exit'


w = World()
run()

Ah, I get it. The way I changed interrogate, it no longer checks for exceptions in a few cases. When Python code called by the C++ task manager triggers an exception, the Python bindings to the C++ function don’t propagate that extension properly to the Python interpreter.
In the case of sys.exit, it simply triggers SystemExit, and that exception gets lost.

I checked in a fix, and that seems to clear everything up. Thanks for the help, guys! :slight_smile:

I’ll look into committing more of tobspr’s changes to ShowBase later, since I do like the idea of not actually calling sys.exit when the window is closed, but just letting run() return.

The bug no longer occurs for me either, great work as usual, rdb.

And thanks for the performance improvements to interrogate. :slight_smile: