[PyQt] segfault using daily snapshot
Phil Thompson
phil at riverbankcomputing.com
Sat Dec 18 12:26:21 GMT 2010
On Sat, 18 Dec 2010 11:40:07 +0100, Erik Janssens
<Erik.Janssens at conceptive.be> wrote:
> Hello Phil
>
> Thank you for your assistance. Yes, threads are involved
> in my tests. The segfault for sure happens during a
> 'deconstruction' phase, most of the time this is at the
> end of the tests, but not always.
>
> I don't think there is any recursive behavior involved,
> our stress tests consist of generating a huge number of
> Camelot form and table views one after another.
>
> I tried to change the code as you suggested to :
>
> static void clear_access_func(sipSimpleWrapper *sw)
> {
> sipAccessFunc old_access_func;
> old_access_func = NULL;
> if (sw->access_func != NULL)
> {
> old_access_func = sw->access_func;
> sw->access_func = NULL;
> }
> if (old_access_func != NULL)
> {
> old_access_func(sw, ReleaseGuard);
> }
> sw->data = NULL;
> }
>
> maybe a bit too much code, but I wanted to be sure.
>
> but it didn't help, still the same effect, I also tried
> to put a SIP_BLOCK_THREADS around the code block, but it
> didn't help either.
>
> would it be possible that a single QObject has multiple
> python wrappers, resulting in duplicate deletes ?
That shouldn't happen.
> what is for sure is that when I comment out the ReleaseGuard
> function, there are no segfaults.
>
> what is the purpose of the ReleaseGuard step ? I don't find
> any docs on it in the qt docs.
It just returns the QPointer to the heap. Without it you get a memory
leak.
> Maybe I should give a bit more background on the issue. We
> have observed a number of segfaults with users of our application.
> What is strange is that this number is far higher with
> Windows 7 users. Also, on Windows 7 the crashes seem more
> severe (push-the-button-time). As this is the only segfault
> I'm able to produce with testing, I suspect it's this issue
> causing the Windows 7 segfaults, but that's not sure of course.
>
> What I could do is deploy a number of apps with the ReleaseGuard
> line removed, to confirm this is the issue, but then I'd like
> to understand what the line is about ?
>
> Another option would be to deploy debug-builds on Windows, but
> I'm really unfamiliar with doing such thing so I'd like to
> avoid it.
>
> Regards,
>
> Erik
I think we need to see if the race condition in Qt is the problem...
In qobject.cpp there is a method QMetaObject::removeGuard(). Can you move
the line...
QMutexLocker locker(guardHashLock());
...so that it is the first line of the method.
Phil
> On Fri, 2010-12-17 at 18:47 +0000, Phil Thompson wrote:
>> On Fri, 17 Dec 2010 09:17:14 +0100, Erik Janssens
>> <Erik.Janssens at conceptive.be> wrote:
>> > Hello Phil,
>> >
>> > please find enclosed a stack trace with a debug build
>> > of the last qt / pyqt releases.
>> >
>> > apart from my stress-tests, I did not yet found an
>> > easy way to reproduce it. but I'm quite sure it affects
>> > our users as well during their daily use.
>> >
>> > I do have a 60Mb core dump of it, but the whole debug
>> > build is more than 700Mb.
>> >
>> > Should you have any hints for me on how to investigate
>> > this further...
>>
>> Nothing looks obviously wrong.
>>
>> Are threads involved in your tests?
>>
>> Does the crash happen during normal execution, or only when the
>> interpreter terminates?
>>
>> SIP gets the address of a C++ instance via an access function. PyQt
>> supplies qpointer_access_func() which uses a QPointer<QObject> so that
it
>> can detect when a QObject created internally by Qt gets deleted. (PyQt
>> can
>> detect when a QObject created by PyQt gets deleted by another
mechanism.)
>> The crash is happening when the resources used to implement the
QPointer
>> are being released when the Python object wrapping the C++ QObject is
>> being
>> garbage collected.
>>
>> I will assume for the moment that QPointer works properly - although
I'm
>> not totally convinced as there seems to be a race condition in
>> QMetaObject::removeGuard().
>>
>> Looking at the implementation of clear_access_func() in siplib.c you
can
>> see that it tries to make sure that the resources are not freed twice
by
>> resetting the the pointer to the access function.
>>
>> Unless there is something fairly obvious that I am missing (which is
>> quite
>> possible) I would start to suspect timing issues - although the stack
>> trace
>> doesn't suggest any recursive behaviour.
>>
>> You might want to try changing clear_access_func() so that it saves the
>> value of sw->access_func, clears it, then calls the access function
using
>> the saved pointer.
>>
>> Phil
>
>
> _______________________________________________
> PyQt mailing list PyQt at riverbankcomputing.com
> http://www.riverbankcomputing.com/mailman/listinfo/pyqt
More information about the PyQt
mailing list