Related
We use posix interval timer (created using timer_create()) in our process that generates SIGALRM on timer expiration. The generated signal is handled asynchronously (sigwait) by a specific thread in the process and we have blocked the signal in all other threads using sig_block. ‘Sig_block’ is invoked in the main thread before the child threads are spawned and so child threads inherit it from parent (i.e., main). However this comes with a caveat that if any of the libraries included in the process spawn any thread during dllmain, the signal will not get blocked in that thread. Also we don't have control over the internal implementation of the DLLs that we include in the process. Can you suggest how to handle this problem? Is there any other way to target the timer expiration signal to specific thread in the process?
I checked the option 'SIGEV_THREAD_ID'. However the documentation states that it is intended only for use by threading libraries.
If you do not mind being Linux-specific, use SIGEV_THREAD_ID. Also, I recommend using a realtime signal (SIGRTMIN+0 through SIGRTMAX-0, inclusive), since these are queued and delivered in the order they were sent.
The reason SIGEV_THREAD_ID is documented as intended for use only by threading libraries is that Linux thread IDs are not normally exposed; this interface is not directly usable with e.g. pthreads. You will need to implement your own gettid():
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/types.h>
#include <sys/syscall.h>
static inline pid_t gettid(void) { return syscall(SYS_gettid); }
That will rely on Linux pthreads not doing anything silly, like switching thread-ids while keeping the same pthread_t ID.
Personally, I suggest a different approach, using a helper thread to maintain the timeouts.
Have a thread maintain a sorted array or a binary heap of timeout timestamps, associated with the target thread ID (pthread_t). The thread will wait in pthread_cond_timedwait() until next timeout expires, or it is signaled, indicating that the timeouts have changed (cancelled or new ones added). When one or more timeouts expire, the thread uses pthread_sigqueue() to send the appropriate signal to the target thread, with the timeout identifier as a payload.
Perhaps a rough simplified sketch helps understand. For simplicity, let's say the pending timeouts form a singly linked list:
struct timeout {
struct timeout *next;
struct timespec when; /* Absolute CLOCK_REALTIME time */
double repeat; /* Refire time in seconds, 0 if single-shot */
pthread_id thread;
int elapsed;
};
pthread_mutex_t timeout_lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t timeout_wait = PTHREAD_COND_INITIALIZER;
struct timeout *timeout_pending = NULL;
int timeout_quit = 0;
static inline int timespec_cmp(const struct timespec t1, const struct timespec t2)
{
return (t1.tv_sec < t2.tv_sec) ? -1 :
(t1.tv_sec > t2.tv_sec) ? +1 :
(t1.tv_nsec < t2.tv_nsec) ? -1 :
(t1.tv_nsec > t2.tv_nsec) ? +1 : 0;
}
static inline void timespec_add(struct timespec *const ts, const double seconds)
{
if (seconds > 0.0) {
ts->tv_sec += (long)seconds;
ts->tv_nsec += (long)(1000000000.0*(double)(seconds - (long)seconds));
if (ts->tv_nsec < 0)
ts->tv_nsec = 0;
if (ts->tv_nsec >= 1000000000) {
ts->tv_sec += ts->tv_nsec / 1000000000;
ts->tv_nsec = ts->tv_nsec % 1000000000;
}
}
}
struct timeout *timeout_arm(double seconds, double repeat)
{
struct timeout *mark;
mark = malloc(sizeof (timeout));
if (!mark) {
errno = ENOMEM;
return NULL;
}
mark->thread = pthread_self();
mark->elapsed = 0;
clock_gettime(CLOCK_REALTIME, &(mark->when));
timespec_add(&(mark->when), seconds);
mark->repeat = repeat;
pthread_mutex_lock(&timeout_lock);
mark->next = timeout_pending;
timeout_pending = mark;
pthread_cond_signal(&timeout_wait);
pthread_mutex_unlock(&timeout_lock);
return mark;
A call to timeout_arm() returns a pointer to the timeout as an identifier, so that the thread can disarm it later:
int timeout_disarm(struct timeout *mark)
{
int result = -1;
pthread_mutex_lock(&timeout_lock);
if (timeout_pending == mark) {
timeout_pending = mark->next;
mark->next = NULL;
result = mark->elapsed;
} else {
struct timeout *list = timeout_pending;
for (; list->next != NULL; list = list->next) {
if (list->next == mark) {
list->next = mark->next;
mark->next = NULL;
result = mark->elapsed;
break;
}
}
}
/* if (result != -1) free(mark); */
pthread_mutex_unlock(&timeout_lock);
return result;
}
Note that the above function does not free() the timeout structure (unless you uncomment the line near the end), and it returns -1 if the timeout cannot be found, and the elapsed field at the time when the timeout was removed if successful.
The thread function managing the timeouts is rather simple:
void *timeout_worker(void *unused)
{
struct timespec when, now;
struct timeout *list;
pthread_mutex_lock(&timeout_lock);
while (!timeout_quit) {
clock_gettime(CLOCK_REALTIME, &now);
/* Let's limit sleeps to, say, one minute in length. */
when = now;
when.tv_sec += 60;
/* Act upon all elapsed timeouts. */
for (list = timeout_pending; list != NULL; list = list->next) {
if (timespec_cmp(now, list->when) >= 0) {
if (!list->elapsed || list->repeat > 0) {
const union sigval value = { .sival_ptr = list };
list->elapsed++;
pthread_sigqueue(list->thread, TIMEOUT_SIGNAL, value);
timespec_add(&(list->when), list->repeat);
}
} else
if (timespec_cmp(when, list->when) < 0) {
when = list->when;
}
}
pthread_cond_timedwait(&timeout_wait, &timeout_lock, &when);
}
/* TODO: Clean up timeouts_pending list. */
return NULL;
}
Note that I haven't checked the above for typos, so there might be some. All code above is licensed under CC0-1.0: do whatever you want, just don't blame me for any errors.
Unfortunately, the behavior you’d like, directing a timer’s signal to a specific thread, is not portable.
To work around your DLL’s naïve behavior — so naïve I’d consider it buggy — you have a few portable options.
You could invoke your program with SIGALRM already blocked, before you exec.
Your timer could specify SIGEV_THREAD instead, and then that thread could either handle the timeout or inform your dedicated thread that it’s time to work.
You could implement the time keeping yourself, without signals, in a synchronously sleeping thread, as Glärbo suggests.
I want to start a timer and have a function called when it expires.
Googling finds lots of examples, including the example in the manual, all of which use sigaction() to set a signal handler.
However, #Patryk says in this question that we can just
void cbf(union sigval);
struct sigevent sev;
timer_t timer;
sev.sigev_notify = SIGEV_THREAD;
sev.sigev_notify_function = cbf; //this function will be called when timer expires
sev.sigev_value.sival_ptr = (void*) arg;//this argument will be passed to cbf
timer_create(CLOCK_MONOTONIC, &sev, &timer);
which is shorter, simpler, cleaner, more maintainable ...
What gives? Is this correct? Is it just a wrapper for sigaction()? Why do the examples explicitly set a signal handler?
Also, if I start a timer either by this method, or by timer_settime and a signal handler, will cancelling the timer casue the system to remove the association between that timer and the callback, or do I have to do that explicitly?
[Update] You can choose either signals or the method I show in my answer below (or both, but that seems silly). It is a matter of taste. Singals might offer a little more fucntionality, at the cost of complciation.
If all you want to do is start a timer and be notified when it expires, the method in my answer is simplest.
Michael Kerrisk has a detailed example in his "The Linux Programming Interface" book:
/* ptmr_sigev_thread.c
This program demonstrates the use of threads as the notification mechanism
for expirations of a POSIX timer. Each of the program's command-line
arguments specifies the initial value and interval for a POSIX timer. The
format of these arguments is defined by the function itimerspecFromStr().
The program creates and arms one timer for each command-line argument.
The timer notification method is specified as SIGEV_THREAD, causing the
timer notifications to be delivered via a thread that invokes threadFunc()
as its start function. The threadFunc() function displays information
about the timer expiration, increments a global counter of timer expirations,
and signals a condition variable to indicate that the counter has changed.
In the main thread, a loop waits on the condition variable, and each time
the condition variable is signaled, the main thread prints the value of the
global variable that counts timer expirations.
Kernel support for Linux timers is provided since Linux 2.6. On older
systems, an incomplete user-space implementation of POSIX timers
was provided in glibc.
*/
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include "curr_time.h" /* Declares currTime() */
#include "tlpi_hdr.h"
#include "itimerspec_from_str.h" /* Declares itimerspecFromStr() */
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int expireCnt = 0; /* Number of expirations of all timers */
static void /* Thread notification function */
threadFunc(union sigval sv)
{
timer_t *tidptr;
int s;
tidptr = sv.sival_ptr;
printf("[%s] Thread notify\n", currTime("%T"));
printf(" timer ID=%ld\n", (long) *tidptr);
printf(" timer_getoverrun()=%d\n", timer_getoverrun(*tidptr));
/* Increment counter variable shared with main thread and signal
condition variable to notify main thread of the change. */
s = pthread_mutex_lock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_lock");
expireCnt += 1 + timer_getoverrun(*tidptr);
s = pthread_mutex_unlock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_unlock");
s = pthread_cond_signal(&cond);
if (s != 0)
errExitEN(s, "pthread_cond_signal");
}
int
main(int argc, char *argv[])
{
struct sigevent sev;
struct itimerspec ts;
timer_t *tidlist;
int s, j;
if (argc < 2)
usageErr("%s secs[/nsecs][:int-secs[/int-nsecs]]...\n", argv[0]);
tidlist = calloc(argc - 1, sizeof(timer_t));
if (tidlist == NULL)
errExit("malloc");
sev.sigev_notify = SIGEV_THREAD; /* Notify via thread */
sev.sigev_notify_function = threadFunc; /* Thread start function */
sev.sigev_notify_attributes = NULL;
/* Could be pointer to pthread_attr_t structure */
/* Create and start one timer for each command-line argument */
for (j = 0; j < argc - 1; j++) {
itimerspecFromStr(argv[j + 1], &ts);
sev.sigev_value.sival_ptr = &tidlist[j];
/* Passed as argument to threadFunc() */
if (timer_create(CLOCK_REALTIME, &sev, &tidlist[j]) == -1)
errExit("timer_create");
printf("Timer ID: %ld (%s)\n", (long) tidlist[j], argv[j + 1]);
if (timer_settime(tidlist[j], 0, &ts, NULL) == -1)
errExit("timer_settime");
}
/* The main thread waits on a condition variable that is signaled
on each invocation of the thread notification function. We
print a message so that the user can see that this occurred. */
s = pthread_mutex_lock(&mtx);
if (s != 0)
errExitEN(s, "pthread_mutex_lock");
for (;;) {
s = pthread_cond_wait(&cond, &mtx);
if (s != 0)
errExitEN(s, "pthread_cond_wait");
printf("main(): expireCnt = %d\n", expireCnt);
}
}
Taken from online source code.
Also read the Chapter 23 of the book, this code is explained in great detail there.
To test the code above, one would enter
$ ./ptmr_sigev_thread 5:5 10:10
This will set two timers: one with initial expiry of 5 seconds and an interval with 5 seconds, and the other with 10 respectively.
The definitions for helper functions can be found by following the link on the book's source code above.
It seems that I do not have to use a signal handler and can make the code much simpler, as shown here:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
static unsigned int pass_value_by_pointer = 42;
void Timer_has_expired(union sigval timer_data)
{
printf("Timer expiration handler function; %d\n", *(int *) timer_data.sival_ptr);
}
int main(void)
{
struct sigevent timer_signal_event;
timer_t timer;
struct itimerspec timer_period;
printf("Create timer\n");
timer_signal_event.sigev_notify = SIGEV_THREAD;
timer_signal_event.sigev_notify_function = Timer_has_expired; // This function will be called when timer expires
// Note that the following is a union. Assign one or the other (preferably by pointer)
//timer_signal_event.sigev_value.sival_int = 38; // This argument will be passed to the function
timer_signal_event.sigev_value.sival_ptr = (void *) &pass_value_by_pointer; // as will this (both in a structure)
timer_signal_event.sigev_notify_attributes = NULL;
timer_create(CLOCK_MONOTONIC, &timer_signal_event, &timer);
printf("Start timer\n");
timer_period.it_value.tv_sec = 1; // 1 second timer
timer_period.it_value.tv_nsec = 0; // no nano-seconds
timer_period.it_interval.tv_sec = 0; // non-repeating timer
timer_period.it_interval.tv_nsec = 0;
timer_settime(timer, 0, &timer_period, NULL);
sleep(2);
printf("----------------------------\n");
printf("Start timer a second time\n");
timer_settime(timer, 0, &timer_period, NULL);
sleep(2);
printf("----------------------------\n");
printf("Start timer a third time\n");
timer_settime(timer, 0, &timer_period, NULL);
printf("Cancel timer\n");
timer_delete(timer);
sleep(2);
printf("The timer expiration handler function should not have been called\n");
return EXIT_SUCCESS;
}
when run, it gives this output:
Create timer
Start timer
Timer expiration handler function; 42
----------------------------
Start timer a second time
Timer expiration handler function; 42
----------------------------
Start timer a third time
Cancel timer
The timer expiration handler function should not have been called
Linux has timerfd. https://lwn.net/Articles/251413/ . This will allows a waitable time to be used together with select/poll/epoll. Alternatively you can use the timeout on select/poll/epoll.
I want to cancel a thread's current task and reset the thread to a
known good state in a very reliable way. I plan to use mlockall and
already preallocate my threads so when I mean reliable I mean
really reliable. The traditional POSIX solution is to use
pthread_cancel to cancel and destroy the thread and then to create a
new replacement thread. However, this solution allocates user stacks
dynamically with mmap (well, GLibc caches thread stacks but this
could change at any time), and allocates kernel stacks dynamically
with clone; and these system calls could fail with errors at any
time so this solution does not work for me.
You cannot just arbitrarily 'reset' a thread of execution to a 'good' state. If you could, we would all be able to fix hung programs by doing so. The only things that can seriously influence a running thread are boolean atomic flags that the thread/task has to check or the OS, (which can always terminate threads).
If you don't want to continually create/stop/terminate threads, (a very good idea indeed), while maintaining some 'task cancellation' functionality, then the thread in question must be signaled somehow to stop running its task and go back to looking for the next one, (eg. on an input producer-consumer queue). If the task is CPU-intensive, you are going to need an atomic 'abort' boolean in the task that is checked at some reasonable frequency. The task can then exit early and allow the thread to get back to the PC-queue, (or whatever feeds it its tasks). If the task has a field that its executing thread can set with its ID, it is possible that the priority of the thread executing the task could be lowered at the same time as the abort bool is set. An oversupply of pooled threads could then ensure that the thread running the aborting task would not interfere with the running of other 'good' tasks. The thread would have to ensure that it raises its priority again after a task exit, so it's ready for the next good task.
I figured out an answer that works with blocking system calls. It's really ugly but it avoids several tricky racy conditions.
First, one registers an empty signal handler for some signal (don't use a real-time signal for this, those can queue up an trap the thread were waiting for in a never ending barrage of signals):
{
struct sigaction act = { 0 };
sigemptyset(&act.sa_mask);
act.sa_handler = do_nothing;
if (-1 == sigaction(SIGUSR1, &act, NULL)) {
perror("sigaction");
return EXIT_FAILURE;
}
}
// ..
static void do_nothing(int signo)
{
}
Then for cancelling one loops sending a signal to the thread doing the operation and polling to see if the thread has cancelled the operation.
void linted_asynch_task_cancel(struct linted_asynch_task *task)
{
int errnum;
errnum = pthread_mutex_lock(&task->owner_lock);
if (errnum != 0) {
assert(errnum != EDEADLK);
assert(false);
}
task->cancelled = true;
/* Yes, really, we do have to busy wait to prevent race
* conditions unfortunately */
while (task->owned) {
errnum = pthread_kill(task->owner, SIGUSR1);
if (errnum != 0 && errnum != EAGAIN) {
assert(errnum != ESRCH);
assert(errnum != EINVAL);
assert(false);
}
errnum = pthread_mutex_unlock(&task->owner_lock);
if (errnum != 0) {
assert(errnum != EPERM);
assert(false);
}
sched_yield();
errnum = pthread_mutex_lock(&task->owner_lock);
if (errnum != 0) {
assert(errnum != EDEADLK);
assert(false);
}
}
errnum = pthread_mutex_unlock(&task->owner_lock);
if (errnum != 0) {
assert(errnum != EPERM);
assert(false);
}
}
The for the actual thread doing the task one simply resubmits a task on EINTR:
static void run_task_sleep_until(struct linted_asynch_pool *pool,
struct linted_asynch_task *task)
{
struct linted_asynch_task_sleep_until *task_sleep = task->data;
int errnum = 0;
int flags = task_sleep->flags;
if (-1 == clock_nanosleep(CLOCK_MONOTONIC, flags, &task_sleep->request,
&task_sleep->request)) {
errnum = errno;
assert(errnum != 0);
}
if (EINTR == errnum) {
linted_asynch_pool_submit(pool, task);
return;
}
task->errnum = errnum;
linted_asynch_pool_complete(pool, task);
}
Finally, in the resubmission function one checks to see if the operation has been cancelled and then completes if with the ECANCELED error if it has:
void linted_asynch_pool_submit(struct linted_asynch_pool *pool,
struct linted_asynch_task *task)
{
bool cancelled;
int errnum;
assert(pool != NULL);
assert(!pool->stopped);
errnum = pthread_mutex_lock(&task->owner_lock);
if (errnum != 0) {
assert(errnum != EDEADLK);
assert(false);
}
task->owned = false;
cancelled = task->cancelled;
errnum = pthread_mutex_unlock(&task->owner_lock);
if (errnum != 0) {
assert(errnum != EPERM);
assert(false);
}
if (cancelled) {
task->errnum = ECANCELED;
linted_queue_send(pool->event_queue, LINTED_UPCAST(task));
} else {
linted_queue_send(pool->worker_command_queue,
LINTED_UPCAST(task));
}
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Loops/timers in C
I've been reading about timers for the last 3 days and I'm unable to find anything useful, I'm trying to understand it in real example, can somebody help me figure out how to setup an alarm for the below program.
How can I set a a timer so that it will send 2 args, one is the array name, and the second one is the number to be deleted, I know the below is not safe in anyway, I'm just trying to understand how use alarms with args to call a function.
please note that the environment is Linux, and also I appreciate any link with a working C example.
#include<stdio.h>
int delete_from_array(int arg) ;
int main()
{
int a[10000], i, y ;
//how to set timer here for to delete any number in array after half a second
for (y=0; y < 100; y++) {
for (i=0; i<sizeof(a) / sizeof(int); i++)
a[i] = i;
sleep(1);
printf("wake\n");
}
}
int delete_from_array(int arg)
{
int i, a[1000], number_to_delete=0;
//number_to_delete = arg->number;
for (i=0; i<sizeof(a); i++)
if (a[i] == number_to_delete)
a[i] = 0;
printf("deleted\n");
}
What I'm trying to do is that I have a hash which has has values to be expired after 1 seconds, so after I insert the value into the hash, I need to create a timer so that it will delete that value after let's say 1 second, and IF I got a response from the server before the that interval (1 second) then I delete the value from the hash and delete the timer, almost like retransmission in tcp
Do you want to use signals or threads?
First, set up the signal handler or prepare a suitable thread function; see man 7 sigevent for details.
Next, create a suitable timer, using timer_create(). See man 2 timer_create for details.
Depending on what you do when the timer fires, you may wish to set the timer to either one-shot, or to repeat at a short interval afterwards. You use timer_settime() to both arm, and to disarm, the timer; see man 2 timer_settime for details.
In practical applications you usually need to multiplex the timer. Even though a process can create multiple timers, they are a limited resource. Especially timeout timers -- which are trivial, either setting a flag and/or sending a signal to a specific thread -- should use a single timer, which fires at the next timeout, sets the related timeout flag, and optionally send a signal (with an empty-body handler) to the desired thread to make sure it is interrupted. (For a single-thread process, the original signal delivery will interrupt blocking I/O calls.) Consider a server, responding to some request: the request itself might have a timeout on the order of a minute or so, while processing the request might need connection timeouts, I/O timeouts, and so on.
Now, the original question is interesting, because timers are powerful when used effectively. However, the example program is basically nonsense. Why don't you create say a program that sets one or more timers, each for example outputting something to standard output? Remember to use write() et al from unistd.h as they are async-signal safe, whereas printf() et cetera from stdio.h are not. (If your signal handlers use non-async-signal safe functions, the results are undefined. It usually works, but it's not guaranteed at all; it may just as well crash as work. Testing will not tell, as it is undefined.)
Edited to add: Here is a bare-bones example of multiplexed timeouts.
(To the extent possible under law, I dedicate all copyright and related and neighboring rights to the code snippets shown below to the public domain worldwide; see CC0 Public Domain Dedication. In other words, feel free to use the code below in any way you wish, just don't blame me for any problems with it.)
I used old-style GCC atomic built-ins, so it should be thread-safe. With a few additions, it should work for multithreaded code too. (You cannot use for example mutexes, because pthread_mutex_lock() is not async-signal safe. Atomically manipulating the timeout states should work, although there might be some races left if you disable a timeout just when it fires.)
#define _POSIX_C_SOURCE 200809L
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#define TIMEOUTS 16
#define TIMEOUT_SIGNAL (SIGRTMIN+0)
#define TIMEOUT_USED 1
#define TIMEOUT_ARMED 2
#define TIMEOUT_PASSED 4
static timer_t timeout_timer;
static volatile sig_atomic_t timeout_state[TIMEOUTS] = { 0 };
static struct timespec timeout_time[TIMEOUTS];
/* Return the number of seconds between before and after, (after - before).
* This must be async-signal safe, so it cannot use difftime().
*/
static inline double timespec_diff(const struct timespec after, const struct timespec before)
{
return (double)(after.tv_sec - before.tv_sec)
+ (double)(after.tv_nsec - before.tv_nsec) / 1000000000.0;
}
/* Add positive seconds to a timespec, nothing if seconds is negative.
* This must be async-signal safe.
*/
static inline void timespec_add(struct timespec *const to, const double seconds)
{
if (to && seconds > 0.0) {
long s = (long)seconds;
long ns = (long)(0.5 + 1000000000.0 * (seconds - (double)s));
/* Adjust for rounding errors. */
if (ns < 0L)
ns = 0L;
else
if (ns > 999999999L)
ns = 999999999L;
to->tv_sec += (time_t)s;
to->tv_nsec += ns;
if (to->tv_nsec >= 1000000000L) {
to->tv_nsec -= 1000000000L;
to->tv_sec++;
}
}
}
/* Set the timespec to the specified number of seconds, or zero if negative seconds.
*/
static inline void timespec_set(struct timespec *const to, const double seconds)
{
if (to) {
if (seconds > 0.0) {
const long s = (long)seconds;
long ns = (long)(0.5 + 1000000000.0 * (seconds - (double)s));
if (ns < 0L)
ns = 0L;
else
if (ns > 999999999L)
ns = 999999999L;
to->tv_sec = (time_t)s;
to->tv_nsec = ns;
} else {
to->tv_sec = (time_t)0;
to->tv_nsec = 0L;
}
}
}
/* Return nonzero if the timeout has occurred.
*/
static inline int timeout_passed(const int timeout)
{
if (timeout >= 0 && timeout < TIMEOUTS) {
const int state = __sync_or_and_fetch(&timeout_state[timeout], 0);
/* Refers to an unused timeout? */
if (!(state & TIMEOUT_USED))
return -1;
/* Not armed? */
if (!(state & TIMEOUT_ARMED))
return -1;
/* Return 1 if timeout passed, 0 otherwise. */
return (state & TIMEOUT_PASSED) ? 1 : 0;
} else {
/* Invalid timeout number. */
return -1;
}
}
/* Release the timeout.
* Returns 0 if the timeout had not fired yet, 1 if it had.
*/
static inline int timeout_unset(const int timeout)
{
if (timeout >= 0 && timeout < TIMEOUTS) {
/* Obtain the current timeout state to 'state',
* then clear all but the TIMEOUT_PASSED flag
* for the specified timeout.
* Thanks to Bylos for catching this bug. */
const int state = __sync_fetch_and_and(&timeout_state[timeout], TIMEOUT_PASSED);
/* Invalid timeout? */
if (!(state & TIMEOUT_USED))
return -1;
/* Not armed? */
if (!(state & TIMEOUT_ARMED))
return -1;
/* Return 1 if passed, 0 otherwise. */
return (state & TIMEOUT_PASSED) ? 1 : 0;
} else {
/* Invalid timeout number. */
return -1;
}
}
int timeout_set(const double seconds)
{
struct timespec now, then;
struct itimerspec when;
double next;
int timeout, i;
/* Timeout must be in the future. */
if (seconds <= 0.0)
return -1;
/* Get current time, */
if (clock_gettime(CLOCK_REALTIME, &now))
return -1;
/* and calculate when the timeout should fire. */
then = now;
timespec_add(&then, seconds);
/* Find an unused timeout. */
for (timeout = 0; timeout < TIMEOUTS; timeout++)
if (!(__sync_fetch_and_or(&timeout_state[timeout], TIMEOUT_USED) & TIMEOUT_USED))
break;
/* No unused timeouts? */
if (timeout >= TIMEOUTS)
return -1;
/* Clear all but TIMEOUT_USED from the state, */
__sync_and_and_fetch(&timeout_state[timeout], TIMEOUT_USED);
/* update the timeout details, */
timeout_time[timeout] = then;
/* and mark the timeout armable. */
__sync_or_and_fetch(&timeout_state[timeout], TIMEOUT_ARMED);
/* How long till the next timeout? */
next = seconds;
for (i = 0; i < TIMEOUTS; i++)
if ((__sync_fetch_and_or(&timeout_state[i], 0) & (TIMEOUT_USED | TIMEOUT_ARMED | TIMEOUT_PASSED)) == (TIMEOUT_USED | TIMEOUT_ARMED)) {
const double secs = timespec_diff(timeout_time[i], now);
if (secs >= 0.0 && secs < next)
next = secs;
}
/* Calculate duration when to fire the timeout next, */
timespec_set(&when.it_value, next);
when.it_interval.tv_sec = 0;
when.it_interval.tv_nsec = 0L;
/* and arm the timer. */
if (timer_settime(timeout_timer, 0, &when, NULL)) {
/* Failed. */
__sync_and_and_fetch(&timeout_state[timeout], 0);
return -1;
}
/* Return the timeout number. */
return timeout;
}
static void timeout_signal_handler(int signum __attribute__((unused)), siginfo_t *info, void *context __attribute__((unused)))
{
struct timespec now;
struct itimerspec when;
int saved_errno, i;
double next;
/* Not a timer signal? */
if (!info || info->si_code != SI_TIMER)
return;
/* Save errno; some of the functions used may modify errno. */
saved_errno = errno;
if (clock_gettime(CLOCK_REALTIME, &now)) {
errno = saved_errno;
return;
}
/* Assume no next timeout. */
next = -1.0;
/* Check all timeouts that are used and armed, but not passed yet. */
for (i = 0; i < TIMEOUTS; i++)
if ((__sync_or_and_fetch(&timeout_state[i], 0) & (TIMEOUT_USED | TIMEOUT_ARMED | TIMEOUT_PASSED)) == (TIMEOUT_USED | TIMEOUT_ARMED)) {
const double seconds = timespec_diff(timeout_time[i], now);
if (seconds <= 0.0) {
/* timeout [i] fires! */
__sync_or_and_fetch(&timeout_state[i], TIMEOUT_PASSED);
} else
if (next <= 0.0 || seconds < next) {
/* This is the soonest timeout in the future. */
next = seconds;
}
}
/* Note: timespec_set() will set the time to zero if next <= 0.0,
* which in turn will disarm the timer.
* The timer is one-shot; it_interval == 0.
*/
timespec_set(&when.it_value, next);
when.it_interval.tv_sec = 0;
when.it_interval.tv_nsec = 0L;
timer_settime(timeout_timer, 0, &when, NULL);
/* Restore errno. */
errno = saved_errno;
}
int timeout_init(void)
{
struct sigaction act;
struct sigevent evt;
struct itimerspec arm;
/* Install timeout_signal_handler. */
sigemptyset(&act.sa_mask);
act.sa_sigaction = timeout_signal_handler;
act.sa_flags = SA_SIGINFO;
if (sigaction(TIMEOUT_SIGNAL, &act, NULL))
return errno;
/* Create a timer that will signal to timeout_signal_handler. */
evt.sigev_notify = SIGEV_SIGNAL;
evt.sigev_signo = TIMEOUT_SIGNAL;
evt.sigev_value.sival_ptr = NULL;
if (timer_create(CLOCK_REALTIME, &evt, &timeout_timer))
return errno;
/* Disarm the timeout timer (for now). */
arm.it_value.tv_sec = 0;
arm.it_value.tv_nsec = 0L;
arm.it_interval.tv_sec = 0;
arm.it_interval.tv_nsec = 0L;
if (timer_settime(timeout_timer, 0, &arm, NULL))
return errno;
return 0;
}
int timeout_done(void)
{
struct sigaction act;
struct itimerspec arm;
int errors = 0;
/* Ignore the timeout signals. */
sigemptyset(&act.sa_mask);
act.sa_handler = SIG_IGN;
if (sigaction(TIMEOUT_SIGNAL, &act, NULL))
if (!errors) errors = errno;
/* Disarm any current timeouts. */
arm.it_value.tv_sec = 0;
arm.it_value.tv_nsec = 0L;
arm.it_interval.tv_sec = 0;
arm.it_interval.tv_nsec = 0;
if (timer_settime(timeout_timer, 0, &arm, NULL))
if (!errors) errors = errno;
/* Destroy the timer itself. */
if (timer_delete(timeout_timer))
if (!errors) errors = errno;
/* If any errors occurred, set errno. */
if (errors)
errno = errors;
/* Return 0 if success, errno otherwise. */
return errors;
}
Remember to include the rt library when compiling, i.e. use gcc -W -Wall *source*.c -lrt -o *binary* to compile.
The idea is that the main program first calls timeout_init() to install all the necessary handlers et cetera, and may call timeout_done() to deistall it before exiting (or in a child process after fork()ing).
To set a timeout, you call timeout_set(seconds). The return value is a timeout descriptor. Currently there is just a flag you can check using timeout_passed(), but the delivery of the timeout signal also interrupts any blocking I/O calls. Thus, you can expect the timeout to interrupt any blocking I/O call.
If you want to do anything more than set a flag at timeout, you cannot do it in the signal handler; remember, in a signal handler, you're limited to async-signal safe functions. The easiest way around that is to use a separate thread with an endless loop over sigwaitinfo(), with the TIMEOUT_SIGNAL signal blocked in all other threads. That way the dedicated thread is guaranteed to catch the signal, but at the same time, is not limited to async-signal safe functions. It can, for example, do much more work, or even send a signal to a specific thread using pthread_kill(). (As long as that signal has a handler, even one with an empty body, its delivery will interrupt any blocking I/O call in that thread.)
Here is a simple example main() for using the timeouts. It is silly, and relies on fgets() not retrying (when interrupted by a signal), but it seems to work.
#include <string.h>
#include <stdio.h>
int main(void)
{
char buffer[1024], *line;
int t1, t2, warned1;
if (timeout_init()) {
fprintf(stderr, "timeout_init(): %s.\n", strerror(errno));
return 1;
}
printf("You have five seconds to type something.\n");
t1 = timeout_set(2.5); warned1 = 0;
t2 = timeout_set(5.0);
line = NULL;
while (1) {
if (timeout_passed(t1)) {
/* Print only the first time we notice. */
if (!warned1++)
printf("\nTwo and a half seconds left, buddy.\n");
}
if (timeout_passed(t2)) {
printf("\nAw, just forget it, then.\n");
break;
}
line = fgets(buffer, sizeof buffer, stdin);
if (line) {
printf("\nOk, you typed: %s\n", line);
break;
}
}
/* The two timeouts are no longer needed. */
timeout_unset(t1);
timeout_unset(t2);
/* Note: 'line' is non-NULL if the user did type a line. */
if (timeout_done()) {
fprintf(stderr, "timeout_done(): %s.\n", strerror(errno));
return 1;
}
return 0;
}
A useful read is the time(7) man page. Notice that Linux also provides the timerfd_create(2) Linux specific syscall, often used with a multiplexing syscall like poll(2) (or ppoll(2) or the older select(2) syscall).
If you want to use signals don't forget to read carefully signal(7) man page (there are restrictions about coding signal handlers; you might want to set a volatile sigatomic_t variable in your signal handlers; you should not do any new or delete -or malloc & free- memory menagenment operations inside a signal handler, where only async-safe function calls are permitted.).
Notice also that event-oriented programming, such as GUI applications, often provide ways (in Gtk, in Qt, with libevent, ....) to manage timers in their event loop.
We have a code a below where it keep ticking for every second it works perfectly fine. The problem starts when we have //select and insert queries need to be process for each and every second we notice there is at time gaps between 1 to 10 seconds. Thus we practically miss some processing to be done. Any idea how to overcome this? Is it that we need to create a separate thread on each second is it?Thank you.
void * reader_thread (void * arg) {
while (1) {
if (flag) {
struct timeval tv;
char timeBuf[10],secondBuf1[100],queryBuf1[500],queryBuf2[500];
char buff[20] = {0};
gettimeofday (&tv, NULL);
//fprintf (stderr, "[%d.%06d] Flag set to 1 on ", tv.tv_sec, tv.tv_usec);
tv.tv_sec -= 5;
strftime(buff, 20, "%Y-%m-%d %H:%M:%S", localtime(&tv.tv_sec));
printf("\nTime is %s", buff);
//select and insert queries
fprintf (stderr, " %s\n", buff);
flag = 0;
}
usleep (100); // will skew the processing but not signal delivery
}
return NULL;
}
void callback (int sig) {
flag = 1; // this is the only thing the callback does
}
int main () {
timer_t tid = 0;
pthread_t thread;
struct itimerspec it;
char *localServer = "localhost", *remoteServer = "localhost";
char *localUser = "user1", *remoteUser = "user2";
char *localPassword = "****", *remotePassword = "*****";
char *localDatabase = "db1", *remoteDatabase = "db1";
localConn = mysql_init(NULL), remoteConn = mysql_init(NULL);
if (!mysql_real_connect(localConn, localServer,
localUser, localPassword, localDatabase, 0, NULL, 0)) {
fprintf(stderr, "%s\n", mysql_error(localConn));
exit(1);
}
pthread_create (&thread, NULL, reader_thread, NULL);
signal (SIGALRM, callback);
it.it_value.tv_sec = 1;
it.it_value.tv_nsec = 0;
it.it_interval.tv_sec = 1;
it.it_interval.tv_nsec = 0;
timer_create (CLOCK_REALTIME, NULL, &tid);
timer_settime (tid, 0, &it, NULL);
while (1) sleep (100);
return 0;
}
Edit codes.
sigset_t sigset;
sigfillset(&sigset);
if (pthread_sigmask(
SIG_BLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
pthread_create (&thread, NULL, reader_thread, NULL);
//sigset_t sigset;
//sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
if (pthread_sigmask(
SIG_UNBLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
You might like to set up this a bit differently:
1 Before spawning any thread use pthread_sigmask() to make the app ignore all signals. This behaviour will then be inheritied by any thread created afterwards and will make them not eat away any signals, as only the main thread is to handle them (see step 2 below).
2 After having created all threads use pthread_sigmask()again to make the main thread receive SIGALRM and use sigaction() (instead of signal(); also see my comment on the OP) to set up the signal handler for SIGALRM.
3 Declare a flag for each thread. Currently a thread resetting the flag might do this before another thread had started.
If the main thread does not have to do anthing alse (or you do not mind spawning another thread): Alternativly to installing a signal handler using sigaction() (as described in step 2 above) you could use something like do { int sig = sigwaitinfo(...); ... } while (1); to pull the signals received from the the queue and set the flags used to trigger the start of the queries.
Update:
Example on how to use pthread_sigmask() to block all signals for the calling thread:
sigset_t sigset;
sigfillset(&sigset);
if (pthread_sigmask(
SIG_BLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
Example on how to use pthread_sigmask() to unblock SIGALRM for the calling thread:
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGALRM);
if (pthread_sigmask(
SIG_UNBLOCK,
&sigset,
NULL))
{
perror("pthread_sigmask");
}
For more details on pthread_sigmask() please see man pthread_sigmask().
Just a suggestion - may/may not be the one you are looking for - you could do something like keep adding the select and insert queries to a queue in reader_thread and have a separate thread for a function which takes the queries from the queue and actually executes them.