Account Options

  1. Sign in
The old Google Groups will be going away soon, but your browser is incompatible with the new version.
Google Groups Home
« Groups Home
Message from discussion Segmentation faults - a theory
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Kevin Ollivier  
View profile  
 More options Sep 20 2012, 12:17 pm
From: Kevin Ollivier <kev...@theolliviers.com>
Date: Thu, 20 Sep 2012 09:17:20 -0700
Local: Thurs, Sep 20 2012 12:17 pm
Subject: Re: [wxPython-dev] Segmentation faults - a theory
Hi Sam,

On Sep 20, 2012, at 4:27 AM, Sam Partington wrote:

> Hi Kevin,

> On 20 September 2012 06:20, Kevin Ollivier <kev...@theolliviers.com> wrote:
>> Any Python extension can crash, this is just reality. Any time you get
>> "closer to the metal" that is the case. You also get speed benefits that
>> come from C++'s simplified and faster methods of managing memory,
>> and without those, Python would probably be too slow to even run GUI
>> apps. So there are trade-offs, it is not a one way issue of getting the
>> 'badness' from C++. You get its good points too, and thanks to Python,
>> you spend a lot less time dealing with its bad parts. Less time is not no time, though.

> Any extension can crash. No extension should crash.  I have no idea
> what you mean by 'closer to the metal', it sounds like a cop out to
> me. "Our extension is too complex to make it safe".

There is a reason there are no pure Python GUIs. All the safety checks Python runs make it impossible to write code that needs to be as fast and tight as GUI code needs to be. You can call that a cop out if you like, but it's a plain fact. Slowing down Destroy() is probably not a huge deal, but if you really want wxPython never to be able to crash under any circumstance, you will indeed need to slow it to the point where it is no longer usable speed-wise.

> You don't know if my proposed fix will slow down wxPython at all, let
> alone noticeably.  Until you have measured the slow down there is no
> way you can decide whether the pay off is worth it or not. If it does
> turn out to be significantly slower then we could certainly make it a
> build time option, and so let the user of the library decide, assuming
> they are happy to build their own version of wxPython, we already do
> this because when we find and fix bugs in wxPython we can't wait for
> the wxPython release cycle to incorporate our fixes (note that I'm
> most definately not complaining here, just stating the facts).  We do
> submit all bug fixes upstream.

> In any case, for the software that my company writes, I would accept a
> slower stable version over a faster unstable version every single
> time.  If performance were that important we wouldn't be using python
> at all.

>>>> In short, use wx.CallAfter or preferably re-design your approach so that you do
>>>> not delete a control within its own event handlers. Maybe just do a
>>>> RemoveChild(widget) on the parent then widget.Hide(), and put it in a deletion queue.

>>> As I said in my other reply to Robin, you just don't know that you are
>>> deleting a control within it's own event handler half the time. We are
>>> now (after at least 10 segfaults caused by this problem) reasonably
>>> aware that we need to tread carefully when using Destroy.

>> The solution is simple - do not do deletion inside event handlers. Schedule them for deletion later. C++ programmers can't do this without getting segfaults either, BTW. ;-)

> You've clearly not read what I wrote in that paragraph which is that
> most of the recent segfaults that we have experienced have not
> resulted from calling Destroy directly in an event handler but from a
> unusual chain of events through several layers of abstraction and
> indirection that would make it more or less impossible to tell from
> inspection that Destroy was being called from an event handler.

If it's more or less impossible for you to know how and where your code is being called, I think that is a (perhaps the) problem.

> As the application complexity increases the likelihood of these things
> taking place increases.

> It is, BTW, completely irrelevant that C++ can cause crashes in the
> same way. It is precisely after 10 years of writing C++ applications
> which would, from time to time, crash when a precondition was not
> meant that we have decided to rewrite the whole thing in python.

>>> Often
>>> enough a CallAfter is sufficient, but not always. We have even had to
>>> do wx.CallAfter(wx.CallLater, .... ) here and there :-)

>>> It's a hack, and I am 99% certain that we have not fixed all of our
>>> potential crashes yet.

>> It's not really a hack, it's how you handle this use case. There are just certain things you should not do inside event handlers.

> See above, we didn't (directly).

It is more correct to say "we didn't realize our code was doing that", but that still means it did do it.

>> Bottom line is that modifying Destroy() on the Python side would
>> probably not be welcomed because it can cause behavior changes
>> in existing apps for whom Destroy() is working as expected. Under
>> the hood behavior changes of this nature for APIs really only make
>> sense when they are fundamentally broken. Destroy() not working in
>> event handlers is not really brokenness from the perspective that it
>> is not meant to be called from them in the first place, in Python or
>> C++ or any language. (Perhaps a note to this effect in the docs
>> would be welcomed, though.)

> I am amazed that you think that the current API of wxPython crashing
> is not fundamentally broken.

The API does, and is designed to, delete the control. There is no better indication of "use with caution" than that. As Peter said, and was quite right about, you ARE using a C++ API, even if you are using it from Python. Python does not have methods like this because they use ref-counting for everything. C++ and wxWidgets sometimes use an object ownership model instead, and that is the case here.

> My proposed fix is to detect Destroy being called from within an event
> handler and only then to behave differently.  I have not yet decided
> whether that should then raise an exception or defer the Destroy.
> Perhaps in this case explicit is better than implicit.

> Yes this would be a behaviour change, but one that I think most users
> would welcome.

> API : Call destroy (directly, or indirectly) from an event handler:

> Current behaviour:  crash your app.
> Proposed behaviour: raise exception, or defer the destroy until is is
> safe to do so.

> I find it hard to imagine that there are many users who would be upset
> about this change in behavior.

Turning an expected Destroy() crash into an exception, provided that you can *always* perfectly determine when Destroy() is going to lead to a crash, is probably not a harmful change. However, that's the sort of change that sounds like it would use some sort of heuristics for determining where it is called from (perhaps parsing a stack trace?), which is probably very tough to get right, and may very well lead to exceptions being thrown when the programmer knows what they're doing and is calling the API in a safe and valid way. Or, also, in some limited cases calling from an event handler may be perfectly acceptable, such as, say, a menu event handler or a user-defined event, which we would now likely forbid. Prediction is very, very hard to get right unconditionally.

In addition, altering Destroy() in this way doesn't help anyone who may trigger a crash, just this specific case, so it's usefulness is limited as well. A more general fix for crashes is probably a much better option. For example, this may more or less solve the problem for you, and not only apply to the Destroy() case, but any possible crash scenario:

http://pypi.python.org/pypi/faulthandler/

In fact, this was included in Python as of 3.3, w00t! :) If this module is reliable (and inclusion suggests it has at least been vetted), I personally would be in favor of including something like this in wxPython, at least for versions < 3.3, as getting a stack trace when a crash does happen is pretty nice, IMHO, and makes tracking down crashes and fixing them much simpler.

Now, deferring the Destroy(), on the other hand, is not just an error catch but a behavior change, and the only way to defer it reasonably would be to make it asynchronous. That means that, for everyone calling it, the Destroy() will now happen at some unknown time. That, to me, is scary. If your wx event queue gets really backed up, it could delay the call for several seconds. In the meantime, code expecting the control to be deleted may run, which could cause any number of unexpected behaviors. This is especially possible if the code has many abstraction layers, as you well know. :)

Regards,

Kevin

> Sam

> --
> To unsubscribe, send email to wxPython-dev+unsubscribe@googlegroups.com
> or visit http://groups.google.com/group/wxPython-dev?hl=en


 
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.