[PyQt] Bug report: crash when using QSytemTrayIcon

Phil Thompson phil at riverbankcomputing.com
Mon Mar 15 12:23:25 GMT 2010


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?

Phil


More information about the PyQt mailing list