Somebody can explain why timer fail with SIGSEGV after 5-7 iteration?
It happens in both cases: with synchronization and without. Operating system is Ubuntu 15.04, Ubuntu GLIBC 2.21-0ubuntu4.
void timer_thread (sigval signal_value) {
printf ("Timer callback!\n");
}
int main(int argc, char* argv[]) {
const int TIMER_COUNT = 300;
for (int i = 0; i < 10000; i++) {
int status = 0;
timer_t timer_id[TIMER_COUNT] = {};
memset(&timer_id[0], 0, sizeof(timer_t)*TIMER_COUNT);
for (int j = 0; j < TIMER_COUNT; j++) {
struct itimerspec ts = {};
struct sigevent se = {};
memset(&ts, 0, sizeof(itimerspec));
memset(&se, 0, sizeof(sigevent));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_int = j;
se.sigev_notify_function = timer_thread;
// Specify a repeating timer that fires each 100000 nanosec.
memset(&ts, 0, sizeof(ts));
ts.it_value.tv_nsec = 100000;
ts.it_interval.tv_nsec = 100000;
status = timer_create(CLOCK_REALTIME, &se, &timer_id[j]);
assert(!status && "Create timer");
status = timer_settime(timer_id[j], 0, &ts, 0);
assert(!status && "Set timer");
}
for (int j = 0; j < TIMER_COUNT; j++) {
usleep(100);
//stop and delete
status = timer_delete(timer_id[j]);
assert(!status && "Fail delete timer");
}
}
printf("Success!\n");
return 0;
}
GDB back trace:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 __pthread_create_2_1 (newthread=newthread@entry=0x7f00e9817e28, attr=attr@entry=0x11c47e8, start_routine=start_routine@entry=0x7f00e93f6eb0 <timer_sigev_thread>, arg=<optimized out>)
at pthread_create.c:711
711 pthread_create.c: No such file or directory.
(gdb) bt
#0 __pthread_create_2_1 (newthread=newthread@entry=0x7f00e9817e28, attr=attr@entry=0x11c47e8, start_routine=start_routine@entry=0x7f00e93f6eb0 <timer_sigev_thread>, arg=<optimized out>)
at pthread_create.c:711
#1 0x00007f00e93f6e7a in timer_helper_thread (arg=<optimized out>) at ../sysdeps/unix/sysv/linux/timer_routines.c:125
#2 0x00007f00e91db6aa in start_thread (arg=0x7f00e9818740) at pthread_create.c:333
#3 0x00007f00e866feed in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
Build command-line: /usr/bin/c++ -lrt -lpthread -g ./main.cc
the following code actually runs, does not crash, cleanly compiles
Notice the expanded time interval for each timer, this is so some 300 timers have time to call printf() and return.
BTW: calling printf()
in a signal handler is a very bad idea
#include <stdio.h> // printf()
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <signal.h>
#include <time.h>
#include <unistd.h> // sleep()
#include <string.h> // memset()
#define TIMER_COUNT (300)
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
void timer_thread (union sigval sigev_value)
{
(void)sigev_value;
static int count = 0;
count++;
fprintf ( stdout, "Timer callback count: %d\n", count);
}
int main( void )
{
timer_t timer_id[TIMER_COUNT];
memset(timer_id, '\0', sizeof(timer_t)*TIMER_COUNT);
struct itimerspec ts;
struct sigevent se;
for (size_t j = 0; j < TIMER_COUNT; j++)
{
memset(&ts, '\0', sizeof(struct itimerspec));
memset(&se, '\0', sizeof(struct sigevent));
se.sigev_notify = SIGEV_THREAD;
se.sigev_value.sival_int = (int)j;
se.sigev_notify_function = timer_thread;
// Specify a repeating timer that fires each 2 second.
ts.it_interval.tv_sec = 2;
ts.it_interval.tv_nsec = 0;
ts.it_value.tv_sec = ts.it_interval.tv_sec;
ts.it_value.tv_nsec = ts.it_interval.tv_nsec;
if( -1 == timer_create(CLOCK_REALTIME, &se, &timer_id[j]) )
errExit( "timer_create failed" );
if( -1 == timer_settime(timer_id[j], 0, &ts, NULL) )
errExit("timer_settime failed");
}
sleep(10);
for (int j = 0; j < TIMER_COUNT; j++)
{
//stop and delete
fprintf( stdout, "stopping timer: %d, with ID: %lu\n", j, (size_t)timer_id[j]);
ts.it_value.tv_sec = 0;
ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
if( -1 == timer_settime( timer_id[j], 0, &ts, NULL) )
errExit("timer_settime (to disable timer) failed" );
fprintf( stdout, "deleting timer: %d, with ID: %lu\n", j, (size_t)timer_id[j]);
if( -1 == timer_delete(timer_id[j]) )
errExit("timer_delete failed" );
}
printf("Success!\n");
return 0;
} // end function: main