pthread waiting on msgrcv does not unblock on timer expiry

Feb 02, 2007 0 Replies

Hi,



I have a issue with running code listed at the end of fedora linux [uname shows - linux 2.6.15-1_2054.FC5, i686]. The same code behaves differently on Red Hat Enterprise Linux (EL4), uname for RL4 machine is - [Linux don.localdomain 2.6.9-42.ELsmp #1 SMP Wed Jul 12 23:32:02 EDT



2006 x86_64 x86_64 x86_64 GNU/Linux] I spawn two pthreads. Both the threads wait on msgQ (msgrcv). I also start two different timers (one posix real time timer(T1) using timer_create and another process-wide timer (T2)using setitimer). The signal tied with setitimer is SIGALRM for signal handler invocation. I wait on msgQ in both threads. When T2 expires, both threads wake up from msgrcv() with perror() showing errno= EINTR on RL4 machine. However, when I run the same program on fedora machine, when T2 expires, msgrcv does not unblock ( I do not see EINTR). Why? Please help. Thanks.

Code Below



++++++++++++++++++++++++++++++++++++++++++

#include #include #include #include #include #include #include #include #include #include #include #include #include



void timeStampPrint(char *fmt, ...); void init_timer(struct itimerval time,long timeout_usec ); void expire_handler(int signum); void timer1_handler(int signum); void *mythreadroutine(void *p); void *mythreadroutine1(void *p); void *print_message_function ( void *ptr ); void setPosixTimer(int ms);



#define OUR_CLOCK CLOCK_REALTIME



char *prog_name; timer_t mytimer=0; int exitLoop = 0; pthread_t testthread;



void timer_intr(int sig, siginfo_t *extra, void *cruft) { timer_t handler_timer; struct itimerspec i; int noverflowp; int *loopPtr; static int timercount; #if 0 if(noverflow=timer_getoverrun(*(timer_t *)extra->si_value.sival_ptr)) { /*timer has overflowed ? error !*/ } #endif



timercount++;



timeStampPrint("timer_intr: received signal=%d.\n",sig); timeStampPrint("timer_intr: siginfo_t: signo=%d, si_code=%d, si_value.sival_ptr=%d.\n",extra->si_signo, extra->si_code, extra->si_value.sival_ptr); //*((int *)extra->si_value.sival_ptr) = 1;



if(timercount == 3) { timeStampPrint("Timercount is %d, stop timer\n",timercount); timercount = 0; i.it_interval.tv_sec=0; i.it_interval.tv_nsec= 0; i.it_value.tv_sec = 0; i.it_value.tv_nsec = 0; loopPtr = (int *)extra->si_value.sival_ptr; timeStampPrint("timer_intr: loopPtr=%d, loopPtrValue=%d, mytimer=%d\n",loopPtr, *loopPtr, mytimer); if(timer_settime(mytimer, 0 , &i, NULL) < 0) { perror("timer_settime failed"); exit(3); } *loopPtr = 24;



} return; }


/* struct sigaction { void (*sa_handler)(int signo); sigset_t sa_mask; int sa_flags; void (*sa_sigaction) (int, siginfo_t *, void *); } */


void * mythreadroutine(void *p) { int c,count; struct itimerspec i; struct timespec resolution; struct sigaction sa; sigset_t allsigs; struct sigevent timer_event; struct itimerval time; unsigned char buf[32]; int mqid = -1; key_t key=6600; int result = 0;



count = 0;



while(mqid < 0) { mqid = msgget(key,0666); timeStampPrint("msgget failed\n"); }


setPosixTimer(20000); init_timer(time,1000000); while(1) { if((result = msgrcv(mqid, buf, 32, 0, 0)) < 0) { perror("mythreadroutine: msgrcv error"); continue; } } }



void * mythreadroutine1(void *p) { int c,count; struct itimerspec i; struct timespec resolution; struct sigaction sa; sigset_t allsigs; struct sigevent timer_event; struct itimerval time; unsigned char buf[32]; int mqid = -1; key_t key=6601; int result = 0;



count = 0;



while(mqid < 0) { mqid = msgget(key,0666); timeStampPrint("msgget failed\n"); }


setPosixTimer(20000); init_timer(time,2000000); while(1) { if((result = msgrcv(mqid, buf, 32, 0, 0)) < 0) { perror("mythreadroutine1: msgrcv error"); continue; } } }



int main(int argc, char **argv) { int result,data1; pthread_t thread1; /* thread variables */ pthread_t thread2; /* thread variables */ int mqid; key_t key=6600; mqid = msgget(key,IPC_CREAT|0666); if(mqid < 0) { timeStampPrint("msgget failed\n"); }



mqid = msgget(6601,IPC_CREAT|0666); if(mqid < 0) { timeStampPrint("msgget failed\n"); }



result = pthread_create (&thread1, NULL, &mythreadroutine, (void



*)&data1); result = pthread_create (&thread2, NULL, &mythreadroutine1, (void
*
)&data1); pthread_join(thread1, NULL); pthread_join(thread2, NULL); exit(0); }


void timeStampPrint(char *fmt, ...) { va_list ap; char str[512]; char timestampbuf[1024]; time_t tm_t; struct tm dateTime; int count;



struct timeval tv; struct tm* ptm; char time_string[40]; long milliseconds;



gettimeofday(&tv, NULL); ptm = localtime(&tv.tv_sec);



strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", ptm); milliseconds = tv.tv_usec / 1000; sprintf(timestampbuf,"[%s.%03ld] ", time_string, milliseconds);


va_start(ap, fmt); vsprintf ( str, fmt, ap ); va_end ( ap );



strcat(timestampbuf,str);



printf("%s",timestampbuf); }


void init_timer(struct itimerval time,long timeout_usec ) { struct sigaction sa = {0,0,0,0,0};



sa.sa_handler = &expire_handler; sigaction (SIGALRM, &sa, NULL);



time.it_interval.tv_sec = 0; time.it_interval.tv_usec = timeout_usec; time.it_value.tv_sec = 0; time.it_value.tv_usec = timeout_usec; setitimer(ITIMER_REAL, &time, NULL); /* Start the timer */ timeStampPrint("Timer for %d usec started.\n",time.it_value.tv_usec);



}


void expire_handler(int signum) { timeStampPrint("timer expired, signum=%d\n"); }



void timer1_handler(int signum) { timeStampPrint("timer expired, signum=%d\n"); }



void *print_message_function ( void *ptr ) { /* do the work */ //printf("Thread %d says %s \n", data->thread_no, data->message); printf("Hello!"); pthread_exit(0); /* exit */ } /* print_message_function ( void *ptr ) */


void setPosixTimer(int ms) { int c,count; struct itimerspec i; struct timespec resolution; struct sigaction sa; sigset_t allsigs; struct sigevent timer_event; struct itimerval time; unsigned char buf[32]; int mqid = -1; key_t key=6600; int result = 0;



count = 0;



//sigemptyset(&sa.sa_mask); sa.sa_flags=SA_SIGINFO; /*real-time signal*/ sa.sa_sigaction=timer_intr; /*pointer to action*/



if(sigaction(SIGRTMIN, &sa, NULL) < 0) { perror("sigaction error"); exit(1); }



i.it_interval.tv_sec=ms/1000; i.it_interval.tv_nsec= ((ms%1000) * 1000000); i.it_value.tv_sec = ms/1000; i.it_value.tv_nsec = ((ms%1000) * 1000000);



/* * * this describes the asynchronous notification to be posted * * upon this timer's expiration: * * * * - use signals * * - send SIGRTMIN * * - send extra data consisting of a pointer back to the timer ID * * cannot pass the timer ID itself because we haven't created it * * yet. * */


exitLoop = 0; timer_event.sigev_notify=SIGEV_SIGNAL; timer_event.sigev_signo= SIGRTMIN; //timer_event.sigev_value.sival_ptr = (void *)&mytimer; timer_event.sigev_value.sival_ptr = (void *)&exitLoop; timeStampPrint("address of exitLoop=%d\n",&exitLoop); if (timer_create(OUR_CLOCK, &timer_event, &mytimer) < 0) { perror("timer create error"); exit(1); }



/* relative timer, go off at the end of the interval*/



timeStampPrint("Timer=%d(addr=%d) invoked.\n",mytimer,&mytimer); if(timer_settime(mytimer, 0 , &i, NULL) < 0) { perror("timer_settime failed "); exit(3); } timeStampPrint("Timer=%d(addr=%d) after timer_settime.\n",mytimer,&mytimer); }



++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Posted via Mailgate.ORG Server - http://www.Mailgate.ORG

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required