Sleeping in a Thread (C / POSIX Threads)

Viewed 25284

I am developing a multithreaded application that makes use of POSIX Threads. I am using threads for doing a periodical job and for that purpose I am using usleep(3) to suspend thread execution. My question is how can I cancel usleep() timer from the main thread, I tried pthread_kill(thread, SIGALRM) but it has a global effect which results in termination of the main application (by default). Here is my pseudo code:

void threaded_task(void *ptr) {
    initialize();

    while(running) {
        do_the_work();
        usleep(some_interval);
    }

    clean_up();
    release_resources();
}

And here is the pseudo function that is used to stop (and gracefully shutdown) given thread from the main thread:

void stop_thread(pthread_t thread) {
    set_running_state(thread, 0); // Actually I use mutex staff
    // TODO: Cancel sleep timer so that I will not wait for nothing.
    // Wait for task to finish possibly running work and clean up 
    pthread_join(thread, NULL);
}

What is the convenient way to achieve my goal? Do I have to use conditional variables or can I do this using sleep() variants?

8 Answers

Maybe you need to mess with the signal mask or maybe signals can't get out of usleep...I don't know. I don know that could use sigwait() or sigtimedwait(). We use pthread_kill to wake threads, but we sleep them using sigwait....not usleep. This is the fastest way I have found to wake do this (40-50x faster than waiting on a pthread_cond according to my tests.)

We do this before creating threads:

int fSigSet;
sigemptyset(&fSigSet);
sigaddset(&fSigSet, SIGUSR1);
sigaddset(&fSigSet, SIGSEGV);
pthread_sigmask(SIG_BLOCK, &fSigSet, NULL);

Every thread created inherits this mask. I get a little confused with the masks. You are either telling the system to not do anything for certain signals or maybe you are telling the system that you are handling some signals...I don't know. Someone else can pipe in and help us out. If I new better how the masks worked, I might be able to tell you that you could just stick the above code in your ThreadProc. Also, I'm not sure if SIGSEGV is necessary.

Then a thread calls this to sleep itself:

int fSigReceived;
// next line sleeps the thread
sigwait(&fSigSet, &fSigReceived);  // assuming you saved fSigSet from above...
// you get here when the thread is woken up by the signal
// you can check fSigReceived if you care what signal you got.

Then you do this to wake a thread:

thread_kill(pThread, SIGUSR1);
Related