I would like to wake up a pthread from another pthread - but after some time. I know signal or pthread_signal with pthread_cond_wait can be used to wake another thread, but I can't see a way to schedule this. The situation would be something like:
THREAD 1:
========
while(1)
recv(low priority msg);
dump msg to buffer
THREAD 2:
========
while(1)
recv(high priority msg);
..do a little bit of processing with msg ..
dump msg to buffer
wake(THREAD3, 5-seconds-later); <-- **HOW TO DO THIS? **
//let some msgs collect for at least a 5 sec window.
//i.e.,Don't wake thread3 immediately for every msg rcvd.
THREAD 3:
=========
while(1)
do some stuff ..
Process all msgs in buffer
sleep(60 seconds).
Any simple way to schedule a wakeup (short of creating a 4th thread that wakes up every second and decides if there is a scheduled entry for thread-3 to wakeup). I really don't want to wakeup thread-3 frequently if there are only low priority msgs in queue. Also, since the messages come in bursts (say 1000 high priority messages in a single burst), I don't want to wake up thread-3 for every single message. It really slows things down (as there is a bunch of other processing stuff it does every time it wakes up).
I am using an ubuntu pc.
How about the use of the pthread_cond_t object available through the pthread API ?
You could share such an object within your threads and let them act on it appropriately.
The resulting code should look like this :
/*
* I lazily chose to make it global.
* You could dynamically allocate the memory for it
* And share the pointer between your threads in
* A data structure through the argument pointer
*/
pthread_cond_t cond_var;
pthread_mutex_t cond_mutex;
int wake_up = 0;
/* To call before creating your threads: */
int err;
if (0 != (err = pthread_cond_init(&cond_var, NULL))) {
/* An error occurred, handle it nicely */
}
if (0 != (err = pthread_mutex_init(&cond_mutex, NULL))) {
/* Error ! */
}
/*****************************************/
/* Within your threads */
void *thread_one(void *arg)
{
int err = 0;
/* Remember you can embed the cond_var
* and the cond_mutex in
* Whatever you get from arg pointer */
/* Some work */
/* Argh ! I want to wake up thread 3 */
pthread_mutex_lock(&cond_mutex);
wake_up = 1; // Tell thread 3 a wake_up rq has been done
pthread_mutex_unlock(&cond_mutex);
if (0 != (err = pthread_cond_broadcast(&cond_var))) {
/* Oops ... Error :S */
} else {
/* Thread 3 should be alright now ! */
}
/* Some work */
pthread_exit(NULL);
return NULL;
}
void *thread_three(void *arg)
{
int err;
/* Some work */
/* Oh, I need to sleep for a while ...
* I'll wait for thread_one to wake me up. */
pthread_mutex_lock(&cond_mutex);
while (!wake_up) {
err = pthread_cond_wait(&cond_var, &cond_mutex);
pthread_mutex_unlock(&cond_mutex);
if (!err || ETIMEDOUT == err) {
/* Woken up or time out */
} else {
/* Oops : error */
/* We might have to break the loop */
}
/* We lock the mutex again before the test */
pthread_mutex_lock(&cond_mutex);
}
/* Since we have acknowledged the wake_up rq
* We set "wake_up" to 0. */
wake_up = 0;
pthread_mutex_unlock(&cond_mutex);
/* Some work */
pthread_exit(NULL);
return NULL;
}
If you want your thread 3 to exit the blocking call to pthread_cond_wait() after a timeout, consider using pthread_cond_timedwait() instead (read the man carefully, the timeout value you supply is the ABSOLUTE time, not the amount of time you don't want to exceed).
If the timeout expires, pthread_cond_timedwait() will return an ETIMEDOUT error.
EDIT : I skipped error checking in the lock / unlock calls, don't forget to handle this potential issue !
EDIT² : I reviewed the code a little bit
You can have the woken thread do the wait itself. In the waking thread:
pthread_mutex_lock(&lock);
if (!wakeup_scheduled) {
wakeup_scheduled = 1;
wakeup_time = time() + 5;
pthread_cond_signal(&cond);
}
pthread_mutex_unlock(&lock);
In the waiting thread:
pthread_mutex_lock(&lock);
while (!wakeup_scheduled)
pthread_cond_wait(&cond, &lock);
pthread_mutex_unlock(&lock);
sleep_until(wakeup_time);
pthread_mutex_lock(&lock);
wakeup_scheduled = 0;
pthread_mutex_unlock(&lock);
Why not just compare the current time to one save earlier?
time_t last_uncond_wakeup = time(NULL);
time_t last_recv = 0;
while (1)
{
if (recv())
{
// Do things
last_recv = time(NULL);
}
// Possible other things
time_t now = time(NULL);
if ((last_recv != 0 && now - last_recv > 5) ||
(now - last_uncond_wakeup > 60))
{
wake(thread3);
last_uncond_wakeup = now;
last_recv = 0;
}
}
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 have some random issues sometimes to join pthread. I can just say that the thread is not stuck in a deadlock with a mutex when the join is failing. Most of the time the thread is idle (sleep syscall) when the timeout occurred on join.
My need is basic. A way to start/stop a thread from the main thread. So I don't need to put mutex in start/stop manager on pthread state variable. The thread is working as an infinite loop most of the time. All my thread are designed with the same skeleton. A start and stop function. The thread function definition. I have a global variable g_event_ctx to store the current status of the thread. running to know I need to cancel it. is_joinable to know if I need to join the thread. Moreover I have sleep/read/write syscall on all my thread function (cancel point !)
typedef struct pthread_context
{
pthread_t id; /*!< pthread_t to be able to stop the thread later */
int running; /*!< allow to know if the thread is currently running */
int is_joinable; /*!< allow to know if the thread is joinable */
} str_pthread_context;
The code of the skeleton :
int start_x_manager (void)
{
pthread_t t_x;
if (g_event_ctx.x_thread.is_joinable) return 0;
PRINT_INFO ("Start x manager");
// start push x thread
if (pthread_create (&t_x, NULL, x_loop_thread, NULL))
PRINT_ERR_GOTO ("error on pthread_create for x thread");
pthread_setname_np(t_x, "x");
g_event_ctx.x_thread.id = t_x;
g_event_ctx.x_thread.is_joinable = 1;
g_event_ctx.x_thread.running = 1;
return 0;
error:
g_event_ctx.x_thread.running = 0;
g_event_ctx.x_thread.is_joinable = 0;
return 1;
}
int stop_x_manager (void)
{
struct timespec ts;
if (!g_event_ctx.x_thread.is_joinable) return 0;
PRINT_INFO ("Stop x manager");
if (g_event_ctx.x_thread.running)
{
CHECK_ERR_GOTO (pthread_cancel(g_event_ctx.x_thread.id) != 0, "Cannot cancel x thread");
g_event_ctx.x_thread.running = 0;
}
CHECK_ERR_GOTO (clock_gettime(CLOCK_REALTIME, &ts) == -1, "Cannot get clock time");
ts.tv_sec += 5;
CHECK_ERR_GOTO (pthread_timedjoin_np (g_event_ctx.x_thread.id, NULL, &ts) != 0, "Cannot join x_thread");
g_event_ctx.x_thread.is_joinable = 0;
return 0;
error:
g_event_ctx.x_thread.running = 0;
g_event_ctx.x_thread.is_joinable = 0;
return 1;
}
The skeleton of the thread function :
void *x_loop_thread (void *arg __attribute__((__unused__)))
{
CHECK_ERR_GOTO (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0, "Cannot set cancel state");
CHECK_ERR_GOTO (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0, "Cannot set cancel state");
PRINT_INFO ("Start x manager loop thread ...");
pthread_cleanup_push(x_manager_cleanup, some_stuff);
while (1)
{
// Do some stuff here
}
g_event_ctx.x_thread.running = 0;
pthread_exit (NULL);
error:
g_event_ctx.x_thread.running = 0;
pthread_cleanup_pop(1);
pthread_exit (NULL);
}
CHECK_ERR_GOTO is a macro which check a condition to know if I need to jump to label error.
What is the reason which can explain a timeout on the pthread_timedjoin_np ? Another piece of code which corrupted my thread id ? Is there a problem of design in my skeleton ?
You can sidestep the problem by putting a variable in the context structure indicating you want the background thread to stop, setting that variable in your main thread before calling join, and checking that variable periodically in the background thread, exiting the while(1) loop if it's true.
If you have any blocking calls that sleep forever, you can either have them time out and loop them with while(!want_to_stop) or, for select loops, add a file descriptor you can activate from the main thread when you want to stop (an eventfd or pipe).
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.
gcc 4.7.2
c89
APR 1.4
Hello,
I am using APR thread pools, event loop (polling), and message queue (msgget, msgsnd, msgrcv).
Currently, I am just testing that if I press ctrl-c. It will set the while to false. So the message will be sent in my signal handler to be received in my while loop.
However, the msgrcv seems to block in my event loop. So I can't get any other events from my library. In my event loop I am checking if a message has been recevied. However, I think it blocks waiting for a message. This will cause my loop to stop looping and I won't be able to capture any event from my library.
This is the first time I have used message queues.
Here is my code, I am only copied the relevent parts so I have removed all error checking to keep it short.
Currently I am just testing that my event loop can receive a message from the queue, so it can stop the loop.
Many thanks for any suggestions,
#define MSG_KEY 0001L
static int msg_id = 0;
static volatile apr_status_t is_looping = FALSE;
/* Wait for these message commands */
typedef enum tag_msg_cmd {END_LOOP, START_LOOP} msg_cmd_e;
/* message queue data */
typedef struct tag_msg_data msg_data_t;
struct tag_msg_data {
long mtype;
msg_cmd_e msg_cmd;
};
int main(void)
{
/* Create message queue */
msg_id = msgget(MSG_KEY, 0666 | IPC_CREAT);
/* Create thread pool */
has_error = apr_thread_pool_create(&thd_pool,
init_threads,
max_threads,
mem_pool_app);
/* Start event loop */
LOG_CHECK(apr_thread_pool_schedule(thd_pool,
(apr_thread_start_t)event_loop,
NULL,
0,
NULL) == APR_SUCCESS, "Failed to schedule event loop");
/* Pause until ctrl-c */
pause();
/* Destroy all memory pools and threading pools */
}
/* Poll for incoming events */
static apr_status_t event_loop(void)
{
msg_data_t msg_data;
int evt_id = 0;
int msg_id = 0;
/* Connect to the message queue */
msg_id = msgget(MSG_KEY, 0644);
assert(msg_id != -1 && "Failed to connect to the message queue");
LOG_DEBUG("Connected to message queue with msg ID [ %d ]", msg_id);
while(is_looping) {
/* Under development - Process incoming event from shared library */
/* evt_id = sr_waitevt(timeout_ms); */
/* process_event(evt_id); */
LOG_DEBUG("Looping....");
/* Should not be blocking here, as I need to receive other events */
msgrcv(msg_id, &msg_data, (sizeof msg_data) - (sizeof(long)), 2, 0);
LOG_DEBUG("Waiting...");
if(msg_data.msg_cmd == END_LOOP) {
LOG_DEBUG("END_LOOP event queue message has been received");
break;
}
sleep(1);
}
return 1;
}
/* Signal handler will terminated application on ctrl-c */
static void signal_handler(int sig)
{
msg_data_t msg_data = {2, END_LOOP};
int rc = 0;
rc = msgsnd(msg_id,
&msg_data,
(sizeof msg_data) - (sizeof(long)),
IPC_NOWAIT);
assert(rc == 0 && "Failed to send data to the message queue");
}
Set the flag parameter on msgrcv (the 5th parm) to IPC_NOWAIT. This makes the queue receive non-blocking.
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.