24

I'm coding the shutdown of a multithreaded server.If everything goes as it should all the threads exit by their own, but there's a small chance that a thread gets stuck.In this case it would be convenient to have a non-blocking join so I could do.

Is there a way of doing a non-blocking pthread_join? Some sort of timed join would be good too.

something like this:

foreach thread do
  nb_pthread_join();
    if still running
      pthread_cancel();

I can think more cases where a a non-bloking join would be useful.

As it seems there is no such a function so I have already coded a workaround, but it's not as simple as I would like.

pseudosavant
  • 7,056
  • 2
  • 36
  • 41
Figo
  • 265
  • 1
  • 2
  • 7

8 Answers8

28

If you are running your application on Linux, you may be interested to know that:

int pthread_tryjoin_np(pthread_t thread, void **retval);

int pthread_timedjoin_np(pthread_t thread, void **retval,
                                const struct timespec *abstime);

Be careful, as the suffix suggests it, "np" means "non-portable". They are not POSIX standard, gnu extensions, useful though.

link to man page

Connor Low
  • 5,900
  • 3
  • 31
  • 52
yves Baumes
  • 8,836
  • 7
  • 45
  • 74
11

The 'pthread_join' mechanism is a convenience to be used if it happens to do exactly what you want. It doesn't do anything you couldn't do yourself, and where it's not exactly what you want, code exactly what you want.

There is no real reason you should actually care whether a thread has terminated or not. What you care about is whether the work the thread was doing is completed. To tell that, have the thread do something to indicate that it is working. How you do that depends on what is ideal for your specific problem, which depends heavily on what the threads are doing.

Start by changing your thinking. It's not a thread that gets stuck, it's what the thread was doing that gets stuck.

David Schwartz
  • 179,497
  • 17
  • 214
  • 278
  • Add sample code please? I have about same problem, a process calls two threads and should only exit once the threads exit -- none of the responses here explained how to do somerthing similar to fork's wait() function. (I added this question to favourites, it'll notify me once you respond automatically) –  Jan 10 '12 at 23:37
  • 3
    Have a boolean, protected by a mutex, that stores the status of the thing you want to know. If desired, use a condition variable to signal you on change of the boolean. – David Schwartz Jan 10 '12 at 23:41
  • Thanks. Sample code would be useful, but I could try to search elsewhere, too. –  Jan 10 '12 at 23:45
  • Is your question just "how do I wait for something"? – David Schwartz Jan 10 '12 at 23:51
  • Yes; [posix threads (pthread_create and pthread_join)](http://stackoverflow.com/questions/6472510) appears to work similarly to what I need, using `pthread_join` ... no problem now. Thank you for your time. –  Jan 11 '12 at 00:11
  • ... ... or not. As I said sample code would be useful, they appear to just do a successful pthread_join call but the thread didn't finish its job. –  Jan 11 '12 at 00:47
  • 3
    @gry Instead of trying to join the thread, wait until the job is finished. This reduces your question to the much simpler -- "how do I wait for something". The answer is, use condition variables. – David Schwartz Jan 11 '12 at 01:08
  • What function should I use to work with condition variables? Do you have a manpage, function name, example to refer me to? (as mentioned earlier, I added this question to favourites, it'll notify me once you respond automatically) –  Jan 11 '12 at 01:25
3

If you're developing for QNX, you can use pthread_timedjoin() function.

Otherwise, you can create a separate thread that will perform pthread_join() and alert the parent thread, by signalling a semaphore for example, that the child thread completes. This separate thread can return what is gets from pthread_join() to let the parent thread determine not only when the child completes but also what value it returns.

dmityugov
  • 4,390
  • 23
  • 18
1

The answer really depends on why you want to do this. If you just want to clean up dead threads, for example, it's probably easiest just to have a "dead thread cleaner" thread that loops and joins.

raldi
  • 21,344
  • 33
  • 76
  • 86
1

I'm not sure what exactly you mean, but I'm assuming that what you really need is a wait and notify mechanism.

In short, here's how it works: You wait for a condition to satisfy with a timeout. Your wait will be over if:

  • The timeout occurs, or
  • If the condition is satisfied.

You can have this in a loop and add some more intelligence to your logic. The best resource I've found for this related to Pthreads is this tutorial: POSIX Threads Programming (https://computing.llnl.gov/tutorials/pthreads/).

I'm also very surprised to see that there's no API for timed join in Pthreads.

Srikanth
  • 11,780
  • 23
  • 72
  • 92
1

There is no timed pthread_join, but if you are waiting for other thread blocked on conditions, you can use timed pthread_cond_timed_wait instead of pthread_cond_wait

shodanex
  • 14,975
  • 11
  • 57
  • 91
1

As others have pointed out there is not a non-blocking pthread_join available in the standard pthread libraries.

However, given your stated problem (trying to guarantee that all of your threads have exited on program shutdown) such a function is not needed. You can simply do this:

int killed_threads = 0;
for(i = 0; i < num_threads; i++) {
   int return = pthread_cancel(threads[i]);
   if(return != ESRCH)
      killed_threads++;
}
if(killed_threads)
    printf("%d threads did not shutdown properly\n", killed_threads)
else
    printf("All threads exited successfully");

There is nothing wrong with calling pthread_cancel on all of your threads (terminated or not) so calling that for all of your threads will not block and will guarantee thread exit (clean or not).

That should qualify as a 'simple' workaround.

Frosty
  • 6,213
  • 3
  • 24
  • 20
  • 25
    This answer is wrong. Having successfully called `pthread_cancel` on each thread does not guarantee that all the threads have exited. They might not have reached any cancellation point, or even if they have, the main thread might get scheduled first and return from `main`, killing the process, before the other threads can finish cleaning up... – R.. GitHub STOP HELPING ICE Jul 07 '11 at 03:32
  • 1
    I think this answer needs a pthread_join() after the pthread_cancel(): "After a canceled thread has terminated, a join with that thread using pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status. (Joining with a thread is the only way to know that cancellation has completed.)" – Zoltan K. Mar 31 '19 at 17:59
0

You could push a byte into a pipe opened as non-blocking to signal to the other thread when its done, then use a non-blocking read to check the status of the pipe.

Doug T.
  • 64,223
  • 27
  • 138
  • 202