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. Disconnect all incoming and outgoing connections from QObject-derived class manually

Disconnect all incoming and outgoing connections from QObject-derived class manually

Scheduled Pinned Locked Moved Unsolved General and Desktop
23 Posts 6 Posters 7.4k Views
  • 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.
  • KroMignonK Offline
    KroMignonK Offline
    KroMignon
    wrote on last edited by
    #8
    This post is deleted!
    1 Reply Last reply
    0
    • A Asperamanca

      I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

      Since I don't just want to solve this one case, but prevent future cases like this, I'd like to move the disconnection of signals and slots to an earlier time, into a destructor of a custom base class of mine. That way, the offending slot would never be called.

      However, I have found no way according to docs to disconnect everything from an object both incoming and outgoing. No list of active connection in QObject or QMetaObject, either. The destructor in QObject does lots of internal stuff, but clearly doesn't use the public-interface disconnect (or similar) methods.

      Any ideas how I can safely disconnect everything to AND from and object?

      KroMignonK Offline
      KroMignonK Offline
      KroMignon
      wrote on last edited by
      #9

      @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

      I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

      IMHO, you have a threading issue here.
      For me, to call a slots during destructor, the call have to be started from another thread and the connection type is Qt::DirectConnection.

      Perhaps you have to look at this?

      A 1 Reply Last reply
      0
      • KroMignonK KroMignon

        @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

        I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

        IMHO, you have a threading issue here.
        For me, to call a slots during destructor, the call have to be started from another thread and the connection type is Qt::DirectConnection.

        Perhaps you have to look at this?

        A Offline
        A Offline
        Asperamanca
        wrote on last edited by
        #10

        @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

        @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

        I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

        IMHO, you have a threading issue here.
        For me, to call a slots during destructor, the call have to be started from another thread and the connection type is Qt::DirectConnection.

        Perhaps you have to look at this?

        No, it's quite clearly not a threading issue. Simply put, I have a custom editable text item derived from QGraphicsObject in a Graphics View hierarchy. If the item is destroyed, it notifies that editing was canceled through a signal.
        Now I connected this signal to a slot of the text editor's parent item. The QGraphicsItem destructor of the parent item (which runs before the QObject destructor) destroys the child, which fires a signal to tell the world text editing was canceled, which calls the slot in my already half-destroyed parent item.

        KroMignonK 1 Reply Last reply
        0
        • A Asperamanca

          @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

          @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

          I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

          IMHO, you have a threading issue here.
          For me, to call a slots during destructor, the call have to be started from another thread and the connection type is Qt::DirectConnection.

          Perhaps you have to look at this?

          No, it's quite clearly not a threading issue. Simply put, I have a custom editable text item derived from QGraphicsObject in a Graphics View hierarchy. If the item is destroyed, it notifies that editing was canceled through a signal.
          Now I connected this signal to a slot of the text editor's parent item. The QGraphicsItem destructor of the parent item (which runs before the QObject destructor) destroys the child, which fires a signal to tell the world text editing was canceled, which calls the slot in my already half-destroyed parent item.

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by
          #11

          @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

          he QGraphicsItem destructor of the parent item (which runs before the QObject destructor) destroys the child, which fires a signal to tell the world text editing was canceled, which calls the slot in my already half-destroyed parent item.

          One solution to avoid this loop is to avoid Qt::DirectConnection and force Qt::QueuedConnection for the cancel signal.
          So the event is store in eventloop and QObject destructor will be called before the cancel event.
          As instance has been destroyed, the event will be thrown by the QEventLoop.

          A 1 Reply Last reply
          3
          • A Asperamanca

            I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

            Since I don't just want to solve this one case, but prevent future cases like this, I'd like to move the disconnection of signals and slots to an earlier time, into a destructor of a custom base class of mine. That way, the offending slot would never be called.

            However, I have found no way according to docs to disconnect everything from an object both incoming and outgoing. No list of active connection in QObject or QMetaObject, either. The destructor in QObject does lots of internal stuff, but clearly doesn't use the public-interface disconnect (or similar) methods.

            Any ideas how I can safely disconnect everything to AND from and object?

            JKSHJ Offline
            JKSHJ Offline
            JKSH
            Moderators
            wrote on last edited by JKSH
            #12

            @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

            I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

            Often, this can be prevented by using deleteLater() to delete your QObjects. This ensures that deletion only occurs after all signals have been processed.

            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

            A 1 Reply Last reply
            5
            • KroMignonK KroMignon

              @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

              he QGraphicsItem destructor of the parent item (which runs before the QObject destructor) destroys the child, which fires a signal to tell the world text editing was canceled, which calls the slot in my already half-destroyed parent item.

              One solution to avoid this loop is to avoid Qt::DirectConnection and force Qt::QueuedConnection for the cancel signal.
              So the event is store in eventloop and QObject destructor will be called before the cancel event.
              As instance has been destroyed, the event will be thrown by the QEventLoop.

              A Offline
              A Offline
              Asperamanca
              wrote on last edited by
              #13

              @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

              @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

              he QGraphicsItem destructor of the parent item (which runs before the QObject destructor) destroys the child, which fires a signal to tell the world text editing was canceled, which calls the slot in my already half-destroyed parent item.

              One solution to avoid this loop is to avoid Qt::DirectConnection and force Qt::QueuedConnection for the cancel signal.
              So the event is store in eventloop and QObject destructor will be called before the cancel event.
              As instance has been destroyed, the event will be thrown by the QEventLoop.

              In this case, this would trigger another bug, since the timing of the signal is quite important in the 99 % of cases where the object is not destroyed. But in general, a solution worthy of consideration.

              KroMignonK 1 Reply Last reply
              0
              • JKSHJ JKSH

                @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.

                Often, this can be prevented by using deleteLater() to delete your QObjects. This ensures that deletion only occurs after all signals have been processed.

                A Offline
                A Offline
                Asperamanca
                wrote on last edited by
                #14

                @JKSH said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                I am trying to solve a crash caused by a slot called during destruction of my class. The problem is, that my own destructor has already run, but QObject's destructor has not yet run, so connections are still active.
                

                Often, this can be prevented by using deleteLater() to delete your QObjects. This ensures that deletion only occurs after all signals have been processed.

                Not here, since GraphicsView will not play along and delete the object anyway...

                1 Reply Last reply
                0
                • A Asperamanca

                  @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                  @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                  he QGraphicsItem destructor of the parent item (which runs before the QObject destructor) destroys the child, which fires a signal to tell the world text editing was canceled, which calls the slot in my already half-destroyed parent item.

                  One solution to avoid this loop is to avoid Qt::DirectConnection and force Qt::QueuedConnection for the cancel signal.
                  So the event is store in eventloop and QObject destructor will be called before the cancel event.
                  As instance has been destroyed, the event will be thrown by the QEventLoop.

                  In this case, this would trigger another bug, since the timing of the signal is quite important in the 99 % of cases where the object is not destroyed. But in general, a solution worthy of consideration.

                  KroMignonK Offline
                  KroMignonK Offline
                  KroMignon
                  wrote on last edited by
                  #15

                  @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                  In this case, this would trigger another bug, since the timing of the signal is quite important in the 99 % of cases where the object is not destroyed. But in general, a solution worthy of consideration.

                  You have to made a choice here, because you have a threading issue. Use queued connection is the easiest way, because it is the QEventLoop which will handle it for you.

                  Another approach, which is not so easy, would be to store QMetaObject::Connection returned by each connect() to the critical slots and disconnect then in your destructor.

                  A 1 Reply Last reply
                  0
                  • KroMignonK KroMignon

                    @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                    In this case, this would trigger another bug, since the timing of the signal is quite important in the 99 % of cases where the object is not destroyed. But in general, a solution worthy of consideration.

                    You have to made a choice here, because you have a threading issue. Use queued connection is the easiest way, because it is the QEventLoop which will handle it for you.

                    Another approach, which is not so easy, would be to store QMetaObject::Connection returned by each connect() to the critical slots and disconnect then in your destructor.

                    A Offline
                    A Offline
                    Asperamanca
                    wrote on last edited by Asperamanca
                    #16

                    @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                    @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                    In this case, this would trigger another bug, since the timing of the signal is quite important in the 99 % of cases where the object is not destroyed. But in general, a solution worthy of consideration.

                    You have to made a choice here, because you have a threading issue. Use queued connection is the easiest way, because it is the QEventLoop which will handle it for you.

                    Another approach, which is not so easy, would be to store QMetaObject::Connection returned by each connect() to the critical slots and disconnect then in your destructor.

                    Why do you believe so firmly it's a threading issue? It isn't, I see the call stack and the parallel stacks in debugger. Also, the behavior is easily explained for any QGraphicsObject, because the QGraphicsItem will delete it's child directly in the destructor, before the destructor of QObject runs (remember that you always have to derive from QObject first, so it's the last to destruct)

                    EDIT: Also, I never used Qt::DirectConnection anywhere in 10 years of coding. So if it was multithreaded, the slot would be called queued.

                    KroMignonK 1 Reply Last reply
                    0
                    • A Asperamanca

                      @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                      @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                      In this case, this would trigger another bug, since the timing of the signal is quite important in the 99 % of cases where the object is not destroyed. But in general, a solution worthy of consideration.

                      You have to made a choice here, because you have a threading issue. Use queued connection is the easiest way, because it is the QEventLoop which will handle it for you.

                      Another approach, which is not so easy, would be to store QMetaObject::Connection returned by each connect() to the critical slots and disconnect then in your destructor.

                      Why do you believe so firmly it's a threading issue? It isn't, I see the call stack and the parallel stacks in debugger. Also, the behavior is easily explained for any QGraphicsObject, because the QGraphicsItem will delete it's child directly in the destructor, before the destructor of QObject runs (remember that you always have to derive from QObject first, so it's the last to destruct)

                      EDIT: Also, I never used Qt::DirectConnection anywhere in 10 years of coding. So if it was multithreaded, the slot would be called queued.

                      KroMignonK Offline
                      KroMignonK Offline
                      KroMignon
                      wrote on last edited by
                      #17

                      @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                      EDIT: Also, I never used Qt::DirectConnection anywhere in 10 years of coding. So if it was multithreaded, the slot would be called queued.

                      If you are not specifying the connection type (Qt::AutoConnection) and sender/emitter are in same thread, it is same are using Qt::DirectConnection.
                      So now you have an issue with this because signals are emitted during execution of your destructor and those signals are executing slots of your currently destroyed instance.
                      If you have used Qt::QueuedConnection, you would not have this issue.

                      I call this "threading issue", and yes it is not the right description. I apologize.

                      JKSHJ 1 Reply Last reply
                      1
                      • KroMignonK KroMignon

                        @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                        EDIT: Also, I never used Qt::DirectConnection anywhere in 10 years of coding. So if it was multithreaded, the slot would be called queued.

                        If you are not specifying the connection type (Qt::AutoConnection) and sender/emitter are in same thread, it is same are using Qt::DirectConnection.
                        So now you have an issue with this because signals are emitted during execution of your destructor and those signals are executing slots of your currently destroyed instance.
                        If you have used Qt::QueuedConnection, you would not have this issue.

                        I call this "threading issue", and yes it is not the right description. I apologize.

                        JKSHJ Offline
                        JKSHJ Offline
                        JKSH
                        Moderators
                        wrote on last edited by
                        #18

                        @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                        @JKSH said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                        Often, this can be prevented by using deleteLater() to delete your QObjects. This ensures that deletion only occurs after all signals have been processed.

                        Not here, since GraphicsView will not play along and delete the object anyway...

                        Ah, I see the problem now.

                        @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                        I call this "threading issue", and yes it is not the right description. I apologize.

                        I'd say "sequencing issue" is a more correct term since everything is occurring on the same thread.

                        Another approach, which is not so easy, would be to store QMetaObject::Connection returned by each connect() to the critical slots and disconnect then in your destructor.

                        I can't think of any nice ways to fix @Asperamanca's problem if he wants to avoid Qt::QueuedConnection too. This solution is probably the best.

                        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                        A 1 Reply Last reply
                        0
                        • JKSHJ JKSH

                          @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                          @JKSH said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                          Often, this can be prevented by using deleteLater() to delete your QObjects. This ensures that deletion only occurs after all signals have been processed.

                          Not here, since GraphicsView will not play along and delete the object anyway...

                          Ah, I see the problem now.

                          @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                          I call this "threading issue", and yes it is not the right description. I apologize.

                          I'd say "sequencing issue" is a more correct term since everything is occurring on the same thread.

                          Another approach, which is not so easy, would be to store QMetaObject::Connection returned by each connect() to the critical slots and disconnect then in your destructor.

                          I can't think of any nice ways to fix @Asperamanca's problem if he wants to avoid Qt::QueuedConnection too. This solution is probably the best.

                          A Offline
                          A Offline
                          Asperamanca
                          wrote on last edited by
                          #19

                          @JKSH
                          Well, I don't like the QueuedConnection solution because it would open a can of worms in order to close a different can of worms...

                          Good solutions would be the ability to disconnect my slots (which disconnect() doesn't offer), or an ability to block my slots (there is a feature to block my signals, but not a similar one for slots).

                          In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                          KroMignonK 1 Reply Last reply
                          0
                          • A Asperamanca

                            @JKSH
                            Well, I don't like the QueuedConnection solution because it would open a can of worms in order to close a different can of worms...

                            Good solutions would be the ability to disconnect my slots (which disconnect() doesn't offer), or an ability to block my slots (there is a feature to block my signals, but not a similar one for slots).

                            In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                            KroMignonK Offline
                            KroMignonK Offline
                            KroMignon
                            wrote on last edited by
                            #20

                            @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                            In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                            It is normal that you don't have a generic solution, because, IMHO your code construction is not very clean. Updating a class when calling class destructor is a kind of "binding loop" issue.

                            You can only disconnect signals from a class instance, because signal is the starting point. A class instance does not known which signal is connect to his slots, this made no sense, for example how should functor/lambda connection be recorded?

                            If you want to disconnect slots, you have to store connect() result and use it to disconnect the slots.

                            A 1 Reply Last reply
                            0
                            • KroMignonK KroMignon

                              @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                              In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                              It is normal that you don't have a generic solution, because, IMHO your code construction is not very clean. Updating a class when calling class destructor is a kind of "binding loop" issue.

                              You can only disconnect signals from a class instance, because signal is the starting point. A class instance does not known which signal is connect to his slots, this made no sense, for example how should functor/lambda connection be recorded?

                              If you want to disconnect slots, you have to store connect() result and use it to disconnect the slots.

                              A Offline
                              A Offline
                              Asperamanca
                              wrote on last edited by
                              #21

                              @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                              @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                              In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                              It is normal that you don't have a generic solution, because, IMHO your code construction is not very clean. Updating a class when calling class destructor is a kind of "binding loop" issue.

                              This is a kind of "damned if you do, damned if you don't" issue. Does destroying a text editor end text editing? Of course it does. And other UI elements may need to adjust to reflect it. Would I prefer to emit the signal before the destructor is called? Of course I would, but my the destructor is the first place I notice I am being destroyed

                              If you want to disconnect slots, you have to store connect() result and use it to disconnect the slots.

                              As a generic solution, also an exercise in futility, since anyone can connect any signal to any slot.

                              KroMignonK JonBJ 2 Replies Last reply
                              0
                              • A Asperamanca

                                @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                                @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                                In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                                It is normal that you don't have a generic solution, because, IMHO your code construction is not very clean. Updating a class when calling class destructor is a kind of "binding loop" issue.

                                This is a kind of "damned if you do, damned if you don't" issue. Does destroying a text editor end text editing? Of course it does. And other UI elements may need to adjust to reflect it. Would I prefer to emit the signal before the destructor is called? Of course I would, but my the destructor is the first place I notice I am being destroyed

                                If you want to disconnect slots, you have to store connect() result and use it to disconnect the slots.

                                As a generic solution, also an exercise in futility, since anyone can connect any signal to any slot.

                                KroMignonK Offline
                                KroMignonK Offline
                                KroMignon
                                wrote on last edited by KroMignon
                                #22

                                @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                                This is a kind of "damned if you do, damned if you don't" issue. Does destroying a text editor end text editing? Of course it does. And other UI elements may need to adjust to reflect it. Would I prefer to emit the signal before the destructor is called? Of course I would, but my the destructor is the first place I notice I am being destroyed

                                I think my english is not good enough to well understand what you have written.

                                What I was trying to say is that triggering signals in your destructor which are connected to himself slots, is not a good code construction.
                                If you do so, you have to handle this in your code by (choose your favorit):

                                • using Qt:QueuedConnection, slot call will be dropped by QEventLoop
                                • storing somewhere the connect() results to disconnect then in your destructor
                                • add a signal aboutToQuit(QObject *) (for example) and use it to disconnect it
                                connect(myObjInstance, &MyObject::aboutToQuit, [this](QObject * obj) { disconnect(obj); });
                                
                                1 Reply Last reply
                                0
                                • A Asperamanca

                                  @KroMignon said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                                  @Asperamanca said in Disconnect all incoming and outgoing connections from QObject-derived class manually:

                                  In the end, I made do with the non-generic, specific solution of manually disconnecting the offending slots in my own destructor.

                                  It is normal that you don't have a generic solution, because, IMHO your code construction is not very clean. Updating a class when calling class destructor is a kind of "binding loop" issue.

                                  This is a kind of "damned if you do, damned if you don't" issue. Does destroying a text editor end text editing? Of course it does. And other UI elements may need to adjust to reflect it. Would I prefer to emit the signal before the destructor is called? Of course I would, but my the destructor is the first place I notice I am being destroyed

                                  If you want to disconnect slots, you have to store connect() result and use it to disconnect the slots.

                                  As a generic solution, also an exercise in futility, since anyone can connect any signal to any slot.

                                  JonBJ Online
                                  JonBJ Online
                                  JonB
                                  wrote on last edited by JonB
                                  #23

                                  @Asperamanca
                                  Having had a good search around, you are not the only person to ask for this, and the answer has always been "It cannot be done". I think the latest request was https://bugreports.qt.io/browse/QTBUG-74691?gerritIssueType=IssueOnly.

                                  The only ways suggested --- to disconnect signals from slots, "disconnect all to receiver" --- was either to keep your own list of connect() return results (which as you say won't work if signal-connectors are external to your code) or to expose "proxy signals" for every signal, which just forward them on, so you can shut them down.

                                  1 Reply Last reply
                                  2

                                  • Login

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