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. [Solved] How to close threads that are blocked by system-level calls?
Forum Updated to NodeBB v4.3 + New Features

[Solved] How to close threads that are blocked by system-level calls?

Scheduled Pinned Locked Moved General and Desktop
3 Posts 1 Posters 2.4k 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.
  • T Offline
    T Offline
    Twinky
    wrote on last edited by
    #1

    I have a thread which blocks until data is received from a system resources such as a USB device. I chose this model because the amount of data may vary, and data may be received at any time. Upon exiting the application, I get the message "QThread: Destroyed while thread is still running". How should I go about closing these threads?

    I've looked at other problems/solutions such as:
    http://www.qtcentre.org/threads/14429-Loop-inside-Qthread-causes-quot-QThread-Destroyed-while-thread-is-still-running-quot
    http://www.qtcentre.org/threads/6211-QThread-Destroyed-while-thread-is-still-running
    The first solution involves using a flag (included in my code) however my thread will never reach the flag check.
    The second solution uses QWaitCondition but seem to be along the same lines as the first.

    I’ve included a stripped down version of the code below. The system calls WaitForSingleObject() is a substitute for what I actually use (GetOverlappedResult()).
    @#ifndef CONTROLLER_H
    #define CONTROLLER_H

    #include <QObject>
    #include <QThread>
    #include <QReadWriteLock>
    #include <QDebug>

    #ifdef Q_OS_WIN
    #include <windows.h>
    #endif // Q_OS_WIN

    #ifdef Q_OS_LINUX
    #include <unistd.h>
    #endif // Q_OS_LINUX

    ////////////////////////////////////////////////
    //
    // Worker Object
    //
    ////////////////////////////////////////////////
    class Worker : public QObject {
    Q_OBJECT

    public:
    QReadWriteLock lock;
    bool running;

    public slots:
    void loop() {
    qDebug() << "entering the loop";
    bool _running;
    forever {

            lock.lockForRead();
            _running = running;
            lock.unlock();
    
            if (!_running) return;
    
            qDebug() << "loop iteration";
    
            #ifdef Q_OS_WIN
                HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
                WaitForSingleObject(event, INFINITE);
            #endif // Q_OS_WIN
    
            #ifdef Q_OS_LINUX
                read(0, 0, 1);
            #endif // Q_OS_LINUX
        }
    }
    

    };

    ////////////////////////////////////////////////
    //
    // Controller
    //
    ////////////////////////////////////////////////
    class Controller {
    public:
    Controller() {
    myWorker.connect(&myThread, SIGNAL(started()), &myWorker, SLOT(loop()));
    myWorker.moveToThread(&myThread);
    myThread.start();
    }

    ~Controller() {
        // Safely close threads
    
        myWorker.lock.lockForWrite();
        myWorker.running = false;
        myWorker.lock.unlock();
    
        myThread.quit();
    
        //myThread.wait();
        //myThread.exit();
        //myThread.terminate();
    }
    

    private:
    QThread myThread;
    Worker myWorker;
    };

    #endif // CONTROLLER_H
    @

    1 Reply Last reply
    0
    • T Offline
      T Offline
      Twinky
      wrote on last edited by
      #2

      Solved.

      On linux, sending a signal to the thread will make read() fail with EINTR. To send the signal I used "sigaction":http://linux.die.net/man/3/sigaction:

      @// Global scope
      void nothing(int signum) {}

      ...

      // Within the start of the thread
      pthread_t myThreadID = pthread_self(); // Get the thread ID
      struct sigaction action;
      action.sa_flags = 0;
      sigemptyset(&action.sa_mask);
      action.sa_handler = nothing;
      sigaction(SIGUSR1, &action, NULL);

      ...

      // When it's time to close the thread
      pthread_kill(myThreadID, SIGUSR1);
      @

      For windows, I believe I can achieve the same effect if I signal the event within the OVERLAPPED structure.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        Twinky
        wrote on last edited by
        #3

        For windows, my thread blocked at GetOverlappedResults(). I stored a HANDLE to an event I created with HANDLE myEvent = CreateEvent(NULL, FALSE, FALSE, NULL); and set the OVERLAPPED's hEvent member to myEvent. To unblock it, I signalled the event with SetEvent(myEvent).

        GetOverlappedResults() http://msdn.microsoft.com/en-us/library/windows/desktop/ms683209(v=vs.85).aspx
        CreateEvent() http://msdn.microsoft.com/en-us/library/windows/desktop/ms682396(v=vs.85).aspx
        SetEvent() http://msdn.microsoft.com/en-us/library/windows/desktop/ms686211(v=vs.85).aspx

        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