[PyQt] Bug report: crash when using QSytemTrayIcon
Phil Thompson
phil at riverbankcomputing.com
Mon Mar 15 13:10:04 GMT 2010
On Mon, 15 Mar 2010 15:40:14 +0300, z <zoomer.gm at gmail.com> wrote:
> 2010/3/15 Phil Thompson <phil at riverbankcomputing.com>
>
>> On Mon, 15 Mar 2010 15:12:01 +0300, z <zoomer.gm at gmail.com> wrote:
>> > 2010/3/15 Phil Thompson <phil at riverbankcomputing.com>
>> >
>> >> On Sun, 14 Mar 2010 22:06:02 +0300, z <zoomer.gm at gmail.com> wrote:
>> >> > 2010/3/5 Phil Thompson <phil at riverbankcomputing.com>
>> >> >
>> >> >> On Fri, 5 Mar 2010 00:35:21 +0100, Kiwi <spiky.kiwi at gmail.com>
>> wrote:
>> >> >> > Hi,
>> >> >> > I'm totally new to PyQt programming.
>> >> >> > While I was writing a very simple app for the system tray I
think
>> >> >> > I
>> >> >> > found
>> >> >> a
>> >> >> > bug.
>> >> >> > Here is a simple testcase:
>> >> >> >
>> >> >> > # -*- coding: utf-8 -*-
>> >> >> > import sys
>> >> >> > from PyQt4 import QtGui, QtCore
>> >> >> >
>> >> >> > app = QtGui.QApplication(sys.argv)
>> >> >> >
>> >> >> > tray = QtGui.QSystemTrayIcon()
>> >> >> >
>> >> >> > def a(): pass
>> >> >> > def b(): pass
>> >> >> > def c(): pass
>> >> >> > def d(): pass
>> >> >> > def e(): pass
>> >> >> > def f(): pass
>> >> >> > def g(): pass
>> >> >> > def h(): pass
>> >> >> > def i(): pass
>> >> >> > def j(): pass
>> >> >> > def k(): pass
>> >> >> >
>> >> >> > cm = QtGui.QMenu()
>> >> >> > cm.addAction("Exit",QtGui.QApplication.quit)
>> >> >> >
>> >> >> > tray.setContextMenu(cm)
>> >> >> >
>> >> >> > tray.show()
>> >> >> > sys.exit(app.exec_())
>> >> >> >
>> >> >> >
>> >> >> > note that the "defs" are needed to make the crash happen.
>> >> >> > FYI, running linux on x86_64
>> >> >> > versions:
>> >> >> > qt: 4.6.2
>> >> >> > pyqt: 4 4.7
>> >> >> > sip: 4.10
>> >> >> > python: 2.6.4
>> >> >> > gcc: 4.4.3
>> >> >> > libX11 1.3.3
>> >> >> >
>> >> >> > here is the backtrace:
>> >> >> > (gdb) run
>> >> >> > Starting program: /usr/bin/python2.6 crash.py
>> >> >> > [Thread debugging using libthread_db enabled]
>> >> >> > QSystemTrayIcon::setVisible: No Icon set
>> >> >> >
>> >> >> > Program received signal SIGSEGV, Segmentation fault.
>> >> >> > XFreeColormap (dpy=0x0, cmap=16777218) at FreeCmap.c:41
>> >> >> > 41 FreeCmap.c: No such file or directory.
>> >> >> > in FreeCmap.c
>> >> >> > (gdb) bt
>> >> >> > #0 XFreeColormap (dpy=0x0, cmap=16777218) at FreeCmap.c:41
>> >> >> > #1 0x00007ffff5f1b558 in ~QSystemTrayIconSys (this=0x9c3070,
>> >> >> > __in_chrg=<value optimized out>) at
>> util/qsystemtrayicon_x11.cpp:213
>> >> >> > #2 0x00007ffff5f19ff4 in QSystemTrayIconPrivate::remove_sys
>> >> >> > (this=0x9bc310) at util/qsystemtrayicon_x11.cpp:352
>> >> >> > #3 0x00007ffff5f0637f in ~QSystemTrayIcon (this=0x8c6590,
>> >> >> > __in_chrg=<value optimized out>) at util/qsystemtrayicon.cpp:152
>> >> >> > #4 0x00007ffff65f46f2 in ~sipQSystemTrayIcon (this=0x8c6590,
>> >> >> > __in_chrg=<value optimized out>) at
>> >> >> > sipQtGuiQSystemTrayIcon.cpp:137
>> >> >> > #5 0x00007ffff65f347c in release_QSystemTrayIcon
>> (sipCppV=0x8c6590,
>> >> >> > sipState=<value optimized out>) at
>> >> >> > sipQtGuiQSystemTrayIcon.cpp:752
>> >> >> > #6 0x00007ffff219c289 in sipWrapper_dealloc (self=0x0) at
>> >> >> > siplib.c:9675
>> >> >> > #7 0x00007ffff7adc0e5 in subtype_dealloc (self=0x7ffff7f1caf0)
>> >> >> > at
>> >> >> > Objects/typeobject.c:1019
>> >> >> > #8 0x00007ffff7aba0cf in insertdict (mp=0x63cf60,
>> >> >> > key=0x7ffff7f08870,
>> >> >> > hash=2314047222216391292, value=0x7ffff7dab5d0) at
>> >> >> > Objects/dictobject.c:459
>> >> >> > #9 0x00007ffff7abcb15 in PyDict_SetItem (op=0x63cf60,
>> >> >> > key=0x7ffff7f08870, value=0x7ffff7dab5d0) at
>> >> >> > Objects/dictobject.c:701
>> >> >> > #10 0x00007ffff7abe48d in _PyModule_Clear (m=<value optimized
>> >> >> > out>)
>> >> >> > at
>> >> >> > Objects/moduleobject.c:138
>> >> >> > #11 0x00007ffff7b2ac4f in PyImport_Cleanup () at
>> Python/import.c:439
>> >> >> > #12 0x00007ffff7b33c46 in Py_Finalize () at
>> >> >> > Python/pythonrun.c:434
>> >> >> > #13 0x00007ffff7b33d58 in Py_Exit (sts=0) at
>> Python/pythonrun.c:1714
>> >> >> > #14 0x00007ffff7b33e87 in handle_system_exit () at
>> >> >> Python/pythonrun.c:1116
>> >> >> > #15 0x00007ffff7b340cd in PyErr_PrintEx (set_sys_last_vars=1) at
>> >> >> > Python/pythonrun.c:1126
>> >> >> > #16 0x00007ffff7b345a6 in PyRun_SimpleFileExFlags
>> >> >> > (fp=0x7fffffffe578,
>> >> >> > filename=0x7fffffffe578 "crash.py", closeit=1,
>> flags=0x7fffffffe0d0)
>> >> >> > at Python/pythonrun.c:935
>> >> >> > #17 0x00007ffff7b40721 in Py_Main (argc=-134926176, argv=<value
>> >> >> > optimized out>) at Modules/main.c:599
>> >> >> > #18 0x00007ffff74ebbbd in __libc_start_main (main=<value
>> >> >> > optimized
>> >> >> > out>, argc=<value optimized out>, ubp_av=<value optimized out>,
>> >> >> > init=<value optimized out>,
>> >> >> > fini=<value optimized out>, rtld_fini=<value optimized out>,
>> >> >> > stack_end=0x7fffffffe1e8) at libc-start.c:220
>> >> >> > #19 0x00000000004006b
>> >> >> > (gdb) f 6
>> >> >> > #6 0x00007ffff219c289 in sipWrapper_dealloc (self=0x0) at
>> >> >> > siplib.c:9675
>> >> >> > 9675 forgetObject((sipSimpleWrapper *)self);
>> >> >> > (gdb) f 5
>> >> >> > #5 0x00007ffff65f347c in release_QSystemTrayIcon
>> (sipCppV=0x8c6590,
>> >> >> > sipState=<value optimized out>) at
>> >> >> > sipQtGuiQSystemTrayIcon.cpp:752
>> >> >> > warning: Source file is more recent than executable.
>> >> >> > 752 delete reinterpret_cast<QSystemTrayIcon
>> *>(sipCppV);
>> >> >> > Current language: auto
>> >> >> > The current source language is "auto; currently c++".
>> >> >> > (gdb) f 4
>> >> >> > #4 0x00007ffff65f46f2 in ~sipQSystemTrayIcon (this=0x8c6590,
>> >> >> > __in_chrg=<value optimized out>) at
>> >> >> > sipQtGuiQSystemTrayIcon.cpp:137
>> >> >> > 137 }
>> >> >>
>> >> >> Crashes on exit like this are caused by Qt objects being deleted
in
>> >> >> the
>> >> >> "wrong" order. Unfortunately PyQt has (almost) no control over
that
>> >> >> order.
>> >> >> By adding those dummy functions you are altering the order in
which
>> >> >> things
>> >> >> get garbage collected. It doesn't happen with C++ applications
>> because
>> >> >> the
>> >> >> objects don't get deleted.
>> >> >>
>> >> >>
>> >> > I found another problem, which i think is also caused by delete
>> >> > order:
>> >> > ######
>> >> > app = QApplication(sys.argv)
>> >> >
>> >> > pushButton = QPushButton()
>> >> > gProxyButton = QGraphicsProxyWidget()
>> >> > gProxyButton.setWidget(pushButton)
>> >> >
>> >> > view = QGraphicsView()
>> >> > view.show()
>> >> >
>> >> > app.exec_()
>> >> > sys.exit()
>> >> > ######
>> >> > on exit this program will crash with segfault.
>> >> > but if the proxy widget will be added to the scene, or explicitly
>> >> > deleted
>> >> > afer app.exec_(), all will be fine
>> >>
>> >> So why would you not add it to a QGraphicsScene?
>> >>
>> >
>> > In my program, i have several items, which will be added to the scene
>> > and
>> > showed only after some event (button click, for ex.). They are
>> > collecting
>> > data, while not being shown, and therefore should persist during all
>> > application lifetime. But the user might exit application, and do not
>> > necessarily trigger their showing action. And application crashes.
>>
>> Wouldn't it be better to always add the widget to the scene, let Qt
>> create
>> the proxy for you, and just hide it until it is needed?
>>
> Yes, in my usecase it is possible to overcome problem this way. But
> requiring an item to be in the scene is a bit strict. Putting such a
> restriction on top of Qt is tricky to find out and debug what's
happening.
> If it can be solved by PyQt itself, the same way as the problem with
> QSysremTrayIcon - it would save some blood of developers. (And PySide
just
> works ;)
The general problem can happen with any sort of object. It only makes sense
to give special treatment to objects involved in common or preferred use
cases.
Phil
More information about the PyQt
mailing list