RajSanpui
RajSanpui

Reputation: 12064

timer_create how to stop recursive thread function invocation after first timer expiry?

I have created a timer using the simple "timer_create". The timer is created using SIGEV_THREAD. That is when the timer expires, there is a call to the timer thread function.

How timer_create works is, suppose assume: expiry=3 secs and timer interval is 1 ns, then the timer keeps ticking every 1 ns until expiry reaches. Once the timer expires, from that instance it keeps on hitting the timer thread function after every 1 ns (timer interval). And keeps on creating one thread per hit till the timer is deleted.

I don't want this to happen, i want once the timer expires, it should go and hit the thread function only once.

How can i achieve this? Can we put any option in timer_create? If not any other timer API?

Thanks a lot in advance

Upvotes: 2

Views: 2934

Answers (2)

gby
gby

Reputation: 15218

Just set timer interval to 0 and expiry to whatever you want. Your timer will expire once (and thread created and run) and then stay disarmed.

Upvotes: 1

R.. GitHub STOP HELPING ICE
R.. GitHub STOP HELPING ICE

Reputation: 215257

I think this is an implementation flaw in the glibc implementation of POSIX timers. There is certainly no way the timer_getoverrun function, which is critical for realtime usage, can work in the glibc implementation, since it returns from the kernel the overrun count for the "current" expiration, but when multiple expiration events are running in parallel, "current" makes no sense. There are also serious issues with resource exhaustion and dropped expiration events which make the implementation unusable for realtime purposes. For example, in nptl/sysdeps/unix/sysv/linux/timer_routines.c:

struct thread_start_data *td = malloc (sizeof (*td));

/* There is not much we can do if the allocation fails.  */
...

In the Linux man page for sigevent, you see for SIGEV_THREAD:

Among the implementation possibilities here are that each timer notification could result in the creation of a new thread, or that a single thread is created to receive all notifications.

The latter is the only choice that could provide correct realtime semantics, but for some reason, glibc did not take this choice.

Here is a possible workaround:

Choose a realtime signal, block that signal before creating any threads, and setup your timer to use that signal with SIGEV_SIGNAL. Now, create a thread for handling your timer(s), and loop on sigwaitinfo, then call your handler function each time it returns. This is actually one possible implementation (and the most-correct implementation) of SIGEV_THREAD which glibc should be using.

Another possibility: there is exactly one synchronization-related, non-syscall-invoking, async-signal-safe function in POSIX: sem_post. Thus it may be possible to make a signal handler (as opposed to getting the signal from sigwaitinfo) synchronize with another thread for the purpose of delivering timer events. But I haven't worked out the details, and it seems like it may be difficult or impossible still.

Upvotes: 4

Related Questions