Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Nested DirectConnection Signals are causing a segfault
Forum Updated to NodeBB v4.3 + New Features

Nested DirectConnection Signals are causing a segfault

Scheduled Pinned Locked Moved General and Desktop
5 Posts 2 Posters 1.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • N Offline
    N Offline
    nullstellensatz
    wrote on last edited by
    #1

    I am using PySide v1.2.2 which wraps the Qt 4.8 framework. I have asked this question on "stack overflow":http://stackoverflow.com/questions/27690865/nested-directconnection-signals-are-causing-a-segfault but wanted to ask it here also to increase the chances of a quick resolution.

    The code, exactly as it is below crashes with a segfault (copy/paste it into your system and run it). When I remove type=QtCore.Qt.DirectConnection from one or both of the signal constructor calls (thereby using QtCore.Qt.AutoConnection instead), everything runs the way it should: A widget appears, showing five progress bars filling up then emptying in an endless loop.

    @from PySide import QtCore, QtGui
    import time

    class Worker(QtCore.QThread):
    sig_worker_update_progress = QtCore.Signal(int, int)

    def __init__(self, thread_id, *args, **kwargs):
        super(Worker, self).__init__(*args, **kwargs)
        self.thread_id = thread_id
        self.stop_requested = False
    
    def slot_interrupt(self):
        self.stop_requested = True
    
    def run(self):
        progress = 0
        while(True):
            self.sig_worker_update_progress.emit(self.thread_id,
                                                                          progress % 100)
            progress += 1
            if self.stop_requested:
                break
            else:
                time.sleep(0.1)
    

    class Controller(QtCore.QObject):
    sig_controller_update_progress = QtCore.Signal(int, int)

    def __init__(self, num_workers, *args, **kwargs):
        super(Controller, self).__init__(*args, **kwargs)
    
        self.workers = []
        for i in range(num_workers):
            self.workers.append(Worker(i))
            self.workers[i].sig_worker_update_progress.connect(
                self.slot_worker_update_progress,
                type=QtCore.Qt.DirectConnection)
        for worker in self.workers:
            worker.start()
    
    def slot_worker_update_progress(self, thread_id, progress):
        # Do
        # Stuff
        self.sig_controller_update_progress.emit(thread_id, progress)
    

    class Monitor(QtGui.QWidget):
    def init(self, num_workers, *args, **kwargs):
    super(Monitor, self).init(*args, **kwargs)
    main_layout = QtGui.QVBoxLayout()
    self.setLayout(main_layout)
    self.progress_bars = []

        for _ in range(num_workers):
            progress_bar = QtGui.QProgressBar()
            main_layout.addWidget(progress_bar)
            self.progress_bars.append(progress_bar)
    
        self.controller  = Controller(num_workers)
        self.controller.sig_controller_update_progress.connect(
            self.slot_controller_update_progress,
            type=QtCore.Qt.DirectConnection)
    
    def slot_controller_update_progress(self, thread_id, progress):
        self.progress_bars[thread_id].setValue(progress)
    

    if name == "main":
    app = QtGui.QApplication([])
    monitor = Monitor(5)
    monitor.show()
    app.exec_()@

    Why does using two nested DirectConnection signals cause a segfault? If Qt does not want you to do that, why isn't a more informative error given?

    1 Reply Last reply
    0
    • Chris KawaC Online
      Chris KawaC Online
      Chris Kawa
      Lifetime Qt Champion
      wrote on last edited by
      #2

      My python is a little rusty but from what I see you emit the signals from a worker thread and update the ui in the connected slot (is that correct?).

      The default type of connection between threads is QueuedConnection and it is executed in the thread the slot owner lives. In your case this is the UI thread, which is fine. The signals from different threads get serializerd in a queue.

      If you change it to DirectConnection it becomes more or less a function call and thus gets executed in the worker thread. There are 2 things wrong with that. First - you can only modify the UI from the main thread. Second - even if you weren't modifying the UI it becomes a race since you've got several threads accessing the same objects.

      1 Reply Last reply
      0
      • N Offline
        N Offline
        nullstellensatz
        wrote on last edited by
        #3

        Hmm that makes sense. Is there a simple way of forcing delivery of all remaining queue items? I used a DirectConnection because the documentation advertised it as a way of ensuring the delivery of items before continuing with program flow. I understand that an AutoConnection is the recommended way of dealing with signals, but my use case needs a guarantee that the queue is cleared when the user presses an "Interrupt" button.

        1 Reply Last reply
        0
        • Chris KawaC Online
          Chris KawaC Online
          Chris Kawa
          Lifetime Qt Champion
          wrote on last edited by
          #4

          The queue is filled constantly by various stuff e.g. signals resulted from events of the OS, not only by your own signals.
          The usual way to deal with this sort of thing is to increment an "atomic counter":http://doc.qt.io/qt-5/qatomicint.html in the worker and then decrement it in the handler. "Interrupt" would then stop the threads and "process events":http://doc.qt.io/qt-5/qcoreapplication.html#processEvents until the counter zeroes.

          1 Reply Last reply
          0
          • N Offline
            N Offline
            nullstellensatz
            wrote on last edited by
            #5

            Great. Thanks!

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved