Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Segmentation fault caused by pthread_kill

GDB tells me that pthread_kill is causing a segmentation fault in my program. Basically I'm using pthread_kill to check if a thread is alive or not given its ID.

I've been searching the web and found that it might be that pthread_kill is causing segmentation fault when TID is invalid. Yes, I have been testing my program using "invalid"(contrived by me) TIDs of type int. Could that be the real cause?

like image 602
Terry Li Avatar asked Dec 12 '11 23:12

Terry Li


2 Answers

pthread_t is not a thread ID, or a numeric index. It is an opaque type. Making up values can result in a crash.

On Linux NPTL, pthread_t is used as a pointer:

int
__pthread_kill (threadid, signo)
     pthread_t threadid;
     int signo;
{
  struct pthread *pd = (struct pthread *) threadid;

It should be fairly clear where things are going wrong already :) Note that this pointerness is also an implementation detail - the older Linuxthreads implementation used numeric indices into a table, and there you could indeed make up TIDs and not expect things to crash.

You need to be tracking thread life and death yourself. A pthread_t is valid until you call pthread_join on it successfully. If you want to test whether a valid pthread_t is alive, call pthread_tryjoin_np on it; if it returns EBUSY, the thread is alive. If the function succeeds, the pthread_t is no longer valid; you must not re-use it at this point - so you must make a note somewhere that that thread is dead now, and there's no need to check it anymore!

You could, of course, implement your own tracking system - create a table somewhere of liveness, a system for handing out TIDs, and passing them into newly created threads. Have each thread mark itself as dead prior to exiting (perhaps using pthread_cleanup_push so you handle thread cancellation and pthread_exit), and detach the thread so you don't need to join it (using pthread_detach). Now you have explicit control of your thread-death reporting.

like image 62
bdonlan Avatar answered Oct 19 '22 18:10

bdonlan


To get around this limitation in my code, I set the TID to zero when the code is not running

memset(&thread, '\0', sizeof(pthread_t)); 

... and check it for null before calling pthread_kill

//this code will run if thread is not valid
if (!thread || ESRCH == pthread_kill(thread, 0)) {
    //do stuff and create the thread
}
like image 25
Joshua Clayton Avatar answered Oct 19 '22 19:10

Joshua Clayton