I’ve got an application written in Python 3.7 using wxPython 4.0.7.post2 running on Windows 7 and 10. About 25% of the time I exit my program the Python interpreter crashes trying to leave MainLoop(). I usually get an error code like (0xC0000005). If I look in the Windows 10 event viewer I can see the program crash and it indicates that the module the fault happened in was wxbase30u_vc140_x64.dll.
I get both of the messages printed. But no further messages are printed at the point that MainLoop() should exit.
The application is too large to post here (~50k LOC). Is there a way to get more information about the crash? Debug into the DLL’s? Anything that could help me track this down?
What does the rest of the EVT_CLOSE handler look like? Does it call event.Skip()? If so, then it is probably due to the C++ part of the frame being destroyed twice.
The close handler does a bit of work to close active network connections, closes a MDI child window, then calls self.DestroyLater() . The event passed into the close handler is not accessed at all.
I’ve pulled down the pdb files and the appropriate source. The problem appears to be in Event.cpp, but I had the wrong source downloaded for that crash, so I don’t know where the real crash is exactly yet. Once I figure that out I’ll likely be back with more questions.
Using the debug files I’ve been able to tell that the crash is happening because a wx.Timer is trying to process an event. I’ve called Stop() and DeletePendingEvents() on all of the wx.Timers I create in my code. Is there any way to stop all wx.Timers() or destroy them in a safe way as part of shutdown? Is there a way to get a list of all wx.Timer objects?
If you use Python Timer the interpreter only stops after all timers have expired, so there will be no crash. The problem is only in the timer handler you have to query the existence of the C++ objects by inserting __nonzero__()
If a frame with a timer is destroyed while the timer is still running, then you do get a crash. That happens even if the event handler doesn’t reference any wrapped C++ objects.
An EVT_WINDOW_DESTROY handler on the frame that stops timers helps with that. Don’t forget event.Skip().
Well, I was actually referring to a Python Timer (see docu of python): that is simply a thread in python, which happens here to be the wrapper of wx. You can destroy as many frames as you like as long as you don’t catch such events as you mentioned the wrapper will happily rap away, I hope
I’m sorry, but that’s not sound: In my_fast_select.py, you are calling wx.StatusBar.SetStatusText from a different thread, not the wx main thread, and that will get you in trouble.
Well, what you say is what the wx docu advises, though in less drastic words. This thread started off with a C++ part still running (the timer still firing) at shut down of the wrapper and, of course, posting more events correctly from a thread doesn’t alleviate the situation, not a bit.
The wx.Timer issue is still in 4.2.1. It have a constant timer in the wx.App, that did not cause any issues, but the main window really could try to run the wx.Timer after the App was destroyed by a different thread and tried to call wx.Timer and caused 0xC0000005.
You should stop wx.Timer before the owner window is destroyed. Otherwise, your app can crash.
Even if it looks fine, sometimes it can (perhaps for large apps).
I generally assumed killing the app would harmlessly kill the timers rather than having me play segfault Russian roulette. Yeah, my app’s a bit large and takes a while to shutdown.
One, but only to be called if there is no gui. So it can’t really be responsible here. Basically it has an internal console with a bunch of commands and usually the GUI does the mainloop but sometimes you could have an async loop for input if you don’t launch with the GUI.
It does have an alternative scheduler thread that sometimes will be there to kill the gui app.
@tatarize
well, I tried a little bit with the wx.App but it looks as though you have to do clean housekeeping (and you are correct the docu does not explicitly say so, although as a subclass of object destroying would be natural)
P.S. I suppose the most economical would be a singleton for the destroy and a binding at each timer creation, like