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. postEvent to potentially destroyed receiver in another thread

postEvent to potentially destroyed receiver in another thread

Scheduled Pinned Locked Moved Solved General and Desktop
posteventthread
5 Posts 4 Posters 908 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.
  • B Offline
    B Offline
    BigOleg
    wrote on 10 Feb 2022, 12:14 last edited by
    #1

    Hello, i am using QCoreApplication::post Event to send result of task from worker thread to an arbitrary receiver that lives in GUI thread. Receiver instance can be deleted during the execution of task. The Worker class stores receiver as QPointer and checks it before passing it to postEvent.

    struct Task
    {
        ...
        QPointer<QObject> receiver;
    };
    ...
    if (task.receiver)  
        QCoreApplication::postEvent(task.receiver, new TaskResultEvent{result}); 
    

    But if the receiver is actually deleted in GUI thread right after QPointer::operator T*() in worker thread the receiver parameter will become dangling and program will crash when trying to access receiver->d_func() inside postEvent.
    Is there safe way to send events for such cases without using signal-slot connections?
    Sorry for my English

    P 1 Reply Last reply 10 Feb 2022, 13:36
    0
    • K Offline
      K Offline
      KH-219Design
      wrote on 10 Feb 2022, 18:24 last edited by KH-219Design 2 Oct 2022, 18:24
      #4

      @BigOleg said in postEvent to potentially destroyed receiver in another thread:

      program will crash when trying to access receiver->d_func() inside postEvent.

      There is a saying that says "often, a sufficiently well-formed problem statement is indistinguishable from a solution."

      You have described the problem very clearly.

      There is indeed a solution that I can envision quite clearly in conceptual terms. I leave it up to you to "port" the following conceptual solution to actual nuts-and-bolts of using QPointer or other Qt features:

      You need another layer of indirection. When the asynchronous event is "unpacked" (currently happening inside the application event loop when the posted-event is actually handled), at that later asynchronous point is when you need to check if (task.receiver) to guard against a crash.

      So you need to "post" a more involved bit of work. You need to queue up something more like a lambda, such that when the application event loop pulls the work off the queue in the GUI thread, the if (task.receiver) happens at THAT point. It needs to happen when the work is dequeued, not when it is enqueued. (Although you may wish to check for null in both places.)

      www.219design.com
      Software | Electrical | Mechanical | Product Design

      1 Reply Last reply
      1
      • B BigOleg
        10 Feb 2022, 12:14

        Hello, i am using QCoreApplication::post Event to send result of task from worker thread to an arbitrary receiver that lives in GUI thread. Receiver instance can be deleted during the execution of task. The Worker class stores receiver as QPointer and checks it before passing it to postEvent.

        struct Task
        {
            ...
            QPointer<QObject> receiver;
        };
        ...
        if (task.receiver)  
            QCoreApplication::postEvent(task.receiver, new TaskResultEvent{result}); 
        

        But if the receiver is actually deleted in GUI thread right after QPointer::operator T*() in worker thread the receiver parameter will become dangling and program will crash when trying to access receiver->d_func() inside postEvent.
        Is there safe way to send events for such cases without using signal-slot connections?
        Sorry for my English

        P Offline
        P Offline
        Pl45m4
        wrote on 10 Feb 2022, 13:36 last edited by
        #2

        @BigOleg

        Cant you just make the Worker stop running as soon as the potential receiver gets destroyed?! Stop your worker and then call deleteLater on your receiver.


        If debugging is the process of removing software bugs, then programming must be the process of putting them in.

        ~E. W. Dijkstra

        1 Reply Last reply
        0
        • B Offline
          B Offline
          BigOleg
          wrote on 10 Feb 2022, 14:48 last edited by
          #3

          The purpose of the worker thread is to manage resources (for example, a connection to a database) whose opening/closing operations are relatively expensive. And widgets (with their lifetime) use this connection to query their data by sending tasks (e.g. query sets) through lightweight task instances.

          1 Reply Last reply
          0
          • K Offline
            K Offline
            KH-219Design
            wrote on 10 Feb 2022, 18:24 last edited by KH-219Design 2 Oct 2022, 18:24
            #4

            @BigOleg said in postEvent to potentially destroyed receiver in another thread:

            program will crash when trying to access receiver->d_func() inside postEvent.

            There is a saying that says "often, a sufficiently well-formed problem statement is indistinguishable from a solution."

            You have described the problem very clearly.

            There is indeed a solution that I can envision quite clearly in conceptual terms. I leave it up to you to "port" the following conceptual solution to actual nuts-and-bolts of using QPointer or other Qt features:

            You need another layer of indirection. When the asynchronous event is "unpacked" (currently happening inside the application event loop when the posted-event is actually handled), at that later asynchronous point is when you need to check if (task.receiver) to guard against a crash.

            So you need to "post" a more involved bit of work. You need to queue up something more like a lambda, such that when the application event loop pulls the work off the queue in the GUI thread, the if (task.receiver) happens at THAT point. It needs to happen when the work is dequeued, not when it is enqueued. (Although you may wish to check for null in both places.)

            www.219design.com
            Software | Electrical | Mechanical | Product Design

            1 Reply Last reply
            1
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 10 Feb 2022, 19:47 last edited by
              #5

              Hi,

              Following @KH-219Design suggestion, you should have a task manager rather than relying on the task object itself to do all the job.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0

              5/5

              10 Feb 2022, 19:47

              • Login

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