线程处理:PyQt崩溃,并显示“队列中有未知请求,同时出队". [英] Threading: PyQt crashes with "unknown request in queue while dequeuing"

查看:243
本文介绍了线程处理:PyQt崩溃,并显示“队列中有未知请求,同时出队".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发的应用程序的一部分需要向少数人发送一些电子邮件.由于可能需要一些时间才能连接到SMTP服务器并发送电子邮件,因此我想在此操作期间提供一个进度栏.我以前几乎没有使用过线程,因此对我来说,使用QThread来证明它有些困难.

One part of an application I'm developing needs to send some emails to a small group of people. Since it may take a little while to connect to the SMTP server and send the emails, I want to provide a progress bar during this operation. I've only barely used threading before, so using QThread to do it has proven somewhat difficult for me.

现在发生的事情是,我可以实现一个工作正常的测试结构,但是一旦我尝试从应用程序后端创建一个对象以实际执行任何电子邮件操作,它就会完全崩溃(就像它崩溃了一样). segfaulted),将其转储到控制台:

What happens now is that I can implement a test structure that works just fine, but then as soon as I try to create an object from the backend of my application to actually do any emailing operations, it crashes completely (as though it had segfaulted), dumping this to the console:

[xcb] Unknown request in queue while dequeuing
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
python: ../../src/xcb_io.c:179: dequeue_pending_request: Assertion `!xcb_xlib_unknown_req_in_deq' failed.
Aborted

我发现搜索这些错误的唯一相关线程说明了错误实施的信号(对于PySide,

The only relevant thread I found searching for these errors said something about the signals being implemented wrong (for PySide, PySide and QProgressBar update in a different thread), but in my case the signals work totally fine until I try to create that object (which isn't based on Qt classes at all).

这是我的GUI代码的简化版本:

Here's a simplified version of my GUI code:

class SendingDialog(QtGui.QDialog):
    def __init__(self, parent, optsDict, cls, zid):
        QtGui.QDialog.__init__(self)
        self.form = Ui_Dialog()
        self.form.setupUi(self)
        # initialize some class variables...

        self.beginConnect()
        self.thread = WorkerThread()
        self.thread.insertOptions(self.opts, self.cls, self.zid)
        self.thread.finished.connect(self.endOfThread)
        self.thread.serverContacted.connect(self.startProgress)
        self.thread.aboutToEmail.connect(self.updateProgress)
        self.thread.start()

    def beginConnect(self):
        # start busy indicator

    def startProgress(self):
        # set up progress bar

    def updateProgress(self):
        # increment progress bar

    def endOfThread(self):
        self.thread.quit()
        self.reject()

class WorkerThread(QtCore.QThread):
    serverContacted = QtCore.pyqtSignal(name="serverContacted")
    aboutToEmail = QtCore.pyqtSignal(name="aboutToEmail")

    def insertOptions(self, opts, cls, zid):
        self.opts = opts
        self.cls = cls
        self.zid = zid

    def run(self):
        # upon running the following line, the application crashes.
        emailman = db.emailing.EmailManager(self.opts, self.cls, self.zid)

如果我在run()中放入一些伪代码,使其休眠,发出适当的信号或打印测试值,则一切正常.但是,一旦我尝试实例化EmailManager,整个过程就会崩溃.

If I put some dummy code into run() that sleeps, emits the appropriate signals, or prints test values, everything works fine; but as soon as I try to instantiate the EmailManager, the whole thing crashes.

EmailManager是从object派生的不起眼的类,采用我给定的参数(opts是字典,cls是另一种类型的类似的不起眼的对象,而zid只是一个简单的数字).构造函数如下所示:

EmailManager is an unremarkable class derived from object, taking the parameters I've given it (opts is a dictionary, cls is a different type of similarly unremarkable object, and zid is just a plain number). The constructor looks like this:

def __init__(self, optsDict, cls, zid):
    self.opts = optsDict
    self.cls = cls
    self.historyItem = HistoryItem(zid)
    self.studentsList = studentsInClass(cls)
    self.connection = None

我正在基于参数构造其他几个对象,但是除此之外,没有发生任何复杂或异常的情况. db.emailing模块中的代码根本不使用Qt或线程.

I'm constructing a couple of other objects based on the parameters, but other than that, nothing complicated or unusual is happening. The code in the db.emailing module does not use Qt or threading at all.

我什至不知道如何开始调试它,因此,关于可能发生的事情或如何尝试找出答案的任何建议将不胜感激.

I don't even know how to begin debugging this, so any advice as to what might be going on or how I could try to find out would be very much appreciated.

编辑:如果有帮助,请参考以下gdb的回溯记录(我对所发生的事情一无所知):

Edit: In case it's helpful, here's the backtrace from gdb (I don't know enough about what's going on to find it helpful):

Program received signal SIGABRT, Aborted.
[Switching to Thread 0x7fffeb146700 (LWP 31150)]
0x00007ffff762acc9 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
56  ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0  0x00007ffff762acc9 in __GI_raise (sig=sig@entry=6)
    at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#1  0x00007ffff762e0d8 in __GI_abort () at abort.c:89
#2  0x00007ffff7623b86 in __assert_fail_base (
    fmt=0x7ffff7774830 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", 
    assertion=assertion@entry=0x7ffff6a4420d "!xcb_xlib_unknown_req_in_deq", file=file@entry=0x7ffff6a441db "../../src/xcb_io.c", line=line@entry=179, 
    function=function@entry=0x7ffff6a446b0 "dequeue_pending_request")
    at assert.c:92
#3  0x00007ffff7623c32 in __GI___assert_fail (
    assertion=0x7ffff6a4420d "!xcb_xlib_unknown_req_in_deq", 
    file=0x7ffff6a441db "../../src/xcb_io.c", line=179, 
    function=0x7ffff6a446b0 "dequeue_pending_request") at assert.c:101
#4  0x00007ffff69d479c in ?? () from /usr/lib/x86_64-linux-gnu/libX11.so.6
#5  0x00007ffff69d55c3 in _XReply ()
   from /usr/lib/x86_64-linux-gnu/libX11.so.6
#6  0x00007ffff69bc346 in XGetWindowProperty ()
   from /usr/lib/x86_64-linux-gnu/libX11.so.6
#7  0x00007ffff69bb22e in XGetWMHints ()
   from /usr/lib/x86_64-linux-gnu/libX11.so.6
#8  0x00007ffff4c87c4b in QWidgetPrivate::setWindowIcon_sys(bool) ()
   from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#9  0x00007ffff4c38405 in QWidget::create(unsigned long, bool, bool) ()
   from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#10 0x00007ffff4c4086a in QWidget::setVisible(bool) ()
   from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#11 0x00007ffff509956e in QDialog::setVisible(bool) ()
   from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#12 0x00007ffff5c24b7c in ?? ()
   from /usr/lib/python2.7/dist-packages/PyQt4/QtGui.so
#13 0x00007ffff5099026 in QDialog::exec() ()
   from /usr/lib/x86_64-linux-gnu/libQtGui.so.4
#14 0x00007ffff5be5fb5 in ?? ()
   from /usr/lib/python2.7/dist-packages/PyQt4/QtGui.so
#15 0x000000000049968d in PyEval_EvalFrameEx ()
#16 0x00000000004a090c in PyEval_EvalCodeEx ()
#17 0x0000000000499a52 in PyEval_EvalFrameEx ()
#18 0x00000000004a1c9a in ?? ()
#19 0x00000000004dfe94 in ?? ()
#20 0x00000000004dc9cb in PyEval_CallObjectWithKeywords ()
#21 0x000000000043734b in PyErr_PrintEx ()
#22 0x00007ffff186fd4d in ?? ()
   from /usr/lib/python2.7/dist-packages/sip.so
#23 0x00007ffff14b2ece in ?? ()
   from /usr/lib/python2.7/dist-packages/PyQt4/QtCore.so
#24 0x00007ffff45be32f in ?? ()
   from /usr/lib/x86_64-linux-gnu/libQtCore.so.4
#25 0x00007ffff79c1182 in start_thread (arg=0x7fffeb146700)
    at pthread_create.c:312
#26 0x00007ffff76ee47d in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111

推荐答案

哇,这很晦涩.

除非明确设置X11窗口函数显然不是线程安全的,否则无论出于何种原因,PyQt都不会自动将其设置为线程安全.可以通过在QApplication构造函数之前添加以下内容来纠正此问题:

The X11 windowing functions are apparently not threadsafe unless explicitly set to be so, and for whatever reason PyQt doesn't automatically set them to be. This can be corrected by adding the following before the QApplication constructor:

QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_X11InitThreads)

请参阅 QApplicationAttributes 上的文档.

就其价值而言,EmailManager现在在线程中启动时 not 不能正常工作,因为它使用共享的SQLite数据库连接来构造其他对象,这与图书馆.我现在也遇到了细分错误.但这至少可以解决.

For what it's worth, EmailManager now does not work correctly when launched in a thread, because it uses a shared SQLite database connection to construct other objects, which is a no-go with the sqlite3 library. I'm also getting segmentation faults now. But this particular problem is solved, at least.

这篇关于线程处理:PyQt崩溃,并显示“队列中有未知请求,同时出队".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆