How to join a thread that is hanging on blocking IO?

Asked
Active3 hr before
Viewed126 times

4 Answers

hanging
90%

Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers ,I have a thread running in the background that is reading events from an input device in a blocking fashion, now when I exit the application I want to clean up the thread properly, but I can't just run a pthread_join() because the thread would never exit due to the blocking IO.,Connect and share knowledge within a single location that is structured and easy to search., How to cite works that is cited in the works

You can play with this very sloppy code I put together to test out my assumptions--I am a couple of timezones away from my POSIX books at the moment...

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <signal.h>

int global_gotsig = 0;

void *gotsig(int sig, siginfo_t *info, void *ucontext) 
{
        global_gotsig++;
        return NULL;
}

void *reader(void *arg)
{
        char buf[32];
        int i;
        int hdlsig = (int)arg;

        struct sigaction sa;
        sa.sa_handler = NULL;
        sa.sa_sigaction = gotsig;
        sa.sa_flags = SA_SIGINFO;
        sigemptyset(&sa.sa_mask);

        if (sigaction(hdlsig, &sa, NULL) < 0) {
                perror("sigaction");
                return (void *)-1;
        }
        i = read(fileno(stdin), buf, 32);
        if (i < 0) {
                perror("read");
        } else {
                printf("Read %d bytes\n", i);
        }
        return (void *)i;
}

main(int argc, char **argv)
{
        pthread_t tid1;
        void *ret;
        int i;
        int sig = SIGUSR1;

        if (argc == 2) sig = atoi(argv[1]);
        printf("Using sig %d\n", sig);

        if (pthread_create(&tid1, NULL, reader, (void *)sig)) {
                perror("pthread_create");
                exit(1);
        }
        sleep(5);
        printf("killing thread\n");
        pthread_kill(tid1, sig);
        i = pthread_join(tid1, &ret);
        if (i < 0)
                perror("pthread_join");
        else
                printf("thread returned %ld\n", (long)ret);
        printf("Got sig? %d\n", global_gotsig);

}
load more v
88%

Mistake # 3: Not realizing that std::thread::join() blocks the calling thread , Mistake # 16: Not realizing that an exception thrown inside an async task is propagated when std::future::get() is invoked. , The solution is to always check if a thread is join-able before trying to join it to the calling thread. , Mistake # 13: Using threads to simulate Asyn jobs when std::async will do

Here's a code snippet if you want to try to simulate a deadlock:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <thread>
#include <mutex>

using namespace std;

std::mutex muA;
std::mutex muB;

void CallHome_AB(string message)
{
  muA.lock();
  //Some additional processing 
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  muB.lock();

  cout << "Thread " << this_thread::get_id() << " says " << message << endl;

  muB.unlock();
  muA.unlock();
}

void CallHome_BA(string message)
{
  muB.lock();
  //Some additional processing 
  std::this_thread::sleep_for(std::chrono::milliseconds(100));
  muA.lock();

  cout << "Thread " << this_thread::get_id() << " says " << message << endl;

  muA.unlock();
  muB.unlock();
}

int main()
{
  thread t1(CallHome_AB, "Hello from Jupiter");
  thread t2(CallHome_BA, "Hello from Pluto");

  t1.join();
  t2.join();

  return 0;
}
load more v
72%

If the thread dump is printed and no deadlocks are found, then the issue might be a bug in which a thread waiting on a monitor that is never notified. This could be a timing issue or a general logic bug.,Threads in the RUNNABLE state might also be blocked. The top frames in the mixed stack should indicate what the thread is doing.,If a thread is in the BLOCKED state and the reason is not clear, then use the -m option to get a mixed stack. With the mixed stack output, it should be possible to identify why the thread is blocked. If a thread is blocked trying to enter a synchronized method or block, then you will see frames such as ObjectMonitor::enter near the top of the stack. Below is an example.,In the jstack output, examine each of the threads in the BLOCKED state. The top frame can sometimes indicate why the thread is blocked, for example, Object.wait or Thread.sleep. The rest of the stack will give an indication of what the thread is doing. This is particularly true when the source has been compiled with line number information (the default) and you can cross reference the source code.

If a thread is in the BLOCKED state and the reason is not clear, then use the -m option to get a mixed stack. With the mixed stack output, it should be possible to identify why the thread is blocked. If a thread is blocked trying to enter a synchronized method or block, then you will see frames such as ObjectMonitor::enter near the top of the stack. Below is an example.

-- -- -- -- -- -- -- -- - t @13-- -- -- -- -- -- -- -- -
0xff31e8b8 ___lwp_cond_wait + 0x4
0xfea8c810 void ObjectMonitor::EnterI(Thread * ) + 0x2b8
0xfeac86b8 void ObjectMonitor::enter2(Thread * ) + 0x250:
65%

A different solution is to avoid blocking the main event loop by performing long operations in a separate thread. This is especially useful if the task is performed by a third party library in a blocking fashion. In such a situation it might not be possible to interrupt it to let the GUI process pending events. , A disadvantage of such an approach is that creating a thumbnail of a single image might take quite long, and for that time the GUI would still be frozen. A better approach would be to perform the operation in a separate thread: , Finally, there is the situation where you have to perform a similar operation on a set of data—for instance, creating thumbnails of pictures from a directory. A trivial implementation would look like this: , Our aim in this article is to keep the functionality while preventing the end user from getting irritated by a frozen GUI (and the network and timers). To do that let's take a look at possible classes of solutions and domains of the problem.

    for (int i = 3; i <= sqrt(x) && isPrime; i += 2) {
       label - > setText(tr("Checking %1...").arg(i));
       if (x % i == 0)
          isPrime = false;
       QCoreApplication::processEvents();
       if (!pushButton - > isChecked()) {
          label - > setText(tr("Aborted"));
          return;
       }
    }
load more v

Other "hanging-undefined" queries related to "How to join a thread that is hanging on blocking IO?"