|
|
Question : pthread_join isn't successfull
|
|
Hi experts, I'm programming an applicationServer which runs under Linux. Server is started by using p_thread_create(). Runnning of the server is no problem. The problem is how to stop the server thread.
I try to stop using sigaction with a handler method. This method calls a member function to call p_thread_cancel() followed by p_thread_join.(see code).The pthread_join is waiting for the server thread to finish but never returns. Program is blocked ! :-( When I call the stop method within the applServer class pthread_join works successfully. Thanks in advance. Martin
Now see the code snippets.
void ServerRestart(int p_iSig); void ServerStop(int p_iSig);
c_ApplServer g_oApplServer(DATASERVERCONFIGFILE);
int main() {
struct sigaction s_SigRestart, s_SigStop;
//start dataserver if (g_oApplServer.start() != 0) exit(0);
s_SigStop.sa_handler = ServerStop; sigemptyset(&s_SigStop.sa_mask); s_SigStop.sa_flags = 0; sigaction(SIGINT,&s_SigStop,NULL); sigaction(SIGTERM,&s_SigStop,NULL); sigaction(SIGQUIT,&s_SigStop,NULL); sigaction(SIGTSTP,&s_SigStop,NULL);
//wait for signals
while(1) pause();
exit(0);
} void ServerStop(int p_iSig) {
printf("Try to stop server\n"); fflush(stdout); g_oApplServer.stop(); exit(0); }
Now the ServerCode snippet: --------------------------
c_ApplServer::c_ApplServer(char *p_pcConfigFile) { a_bServerRun = true; } c_ApplServer::~c_ApplServer() { }
int c_ApplServer::start(void) {
if(pthread_create(&a_ThreadServer,NULL,ThreadServerWatchFunction,this) != 0) { } return 0; }
int c_ApplServer::restart(void) { return 0; }
int c_ApplServer::stop(void) { int res; //a_bServerRun = false; sleep(1);
printf("Waiting for Server thread to finish\n"); fflush(stdout); if(pthread_cancel(a_ThreadServer)!= 0) { fprintf(stderr,"Cancel ThreadServer failed\n"); }
if(pthread_join(a_ThreadServer, NULL)!=0) { fprintf(stderr,"Thread joining failed\n"); } fflush(stdout);
return 0; }
void *c_ApplServer::ThreadServerWatchFunction(void* p_pvArg) { c_ApplServer *l_poApplServer = (c_ApplServer*)p_pvArg; l_poApplServer -> ThreadServerWatch(p_pvArg);
return NULL; }
void c_ApplServer::ThreadServerWatch(void* p_pvArg) {
//c_ApplServer* appl = (c_ApplServer*)p_pvArg; int res = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while(1) { printf("I'm running... \n"); pthread_testcancel(); usleep(500); pthread_testcancel(); }
}
|
Answer : pthread_join isn't successfull
|
|
I was playing with your code, and as you said sometimes it fails. I think it is because when the interrupt signal is received, any thread can run the signal handler. Ie the signal handler method is run from one of the threads. If you want to control this, you should block the signal in the threads where you don't want to handle it.
something like this, and the problem seems to disappear....
int main() { struct sigaction s_SigStop;
// mask the signals before we create the thread sigset_t mask; //start dataserver sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGSTOP); sigaddset(&mask, SIGQUIT);
pthread_sigmask(SIG_BLOCK, &mask, NULL); if (g_oApplServer.start() != 0) exit(0);
//now that we have created the thread, we unblock the signal //and we install the signal handler, this will make sure that the //only thread that will accept this signal is the main thread ..
pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
s_SigStop.sa_handler = ServerStop; sigemptyset(&s_SigStop.sa_mask); s_SigStop.sa_flags = 0; sigaction(SIGINT,&s_SigStop,NULL); sigaction(SIGTERM,&s_SigStop,NULL); sigaction(SIGQUIT,&s_SigStop,NULL); sigaction(SIGTSTP,&s_SigStop,NULL);
//wait for signals
while(1) pause();
exit(0);
}
|
|
|
|
|