I have more then three timer running from main as given below, and I have defined one message queue in main section. My timer's expiration time in 10(max).
Why, when timer expires "msgrcv" gives error like "Interrupted system call"?
timer_t timer1 = create_timer(TT_SIGUSR1);
install_sighandler(TT_SIGUSR1, signal_handler);
set_timer(timer1, TIME_INTERVAL_1);
-
-
-
flag = IPC_CREAT | 0666;
key = 1234;
msgqid = msgget(key,flag);
printf("msgqid = %d\n",msgqid);
while (1)
{
msgsz = msgrcv(msgqid, &sendMsg, sizeof(sendMsg), 0,0);
perror("prashant");
sleep(1);
}
return 0;
Because you probably setup your timer to send you a signal when it expires. Receiving a signal while blocked on certain system calls will make said system calls fail with errno = EINTR.
The msgrcv() function shall fail if:
[EINTR]
The msgrcv() function was interrupted by a signal.
Related
I am writing a sample program where my main() will create a thread and then it will start a timer. When the timer expires, the thread should get the signal. This is on Ubuntu 18.04.4 LTS.
My problem is that timer_create() is failing and error number is set to EINVAL. My snippet of code for timer_create() is given below.
/* Create the timer */
sevp.sigev_notify = SIGEV_THREAD_ID;
sevp.sigev_signo = SIGALRM;
sevp.sigev_value.sival_int = somevalue;
sevp._sigev_un._tid = threadid;
retval = timer_create(CLOCK_MONOTONIC,&sevp,&timerid);
if ( 0 == retval )
{
printf("Success in creating timer [%p]",timerid);
}
else
{
printf("Error in creating timer [%s]\n",strerror(errno));
}
What am I doing wrong?
As per the linux man page entry for timer_create with SIGEV_THREAD_ID:
As for SIGEV_SIGNAL, but the signal is targeted at the thread
whose ID is given in sigev_notify_thread_id, which must be a
thread in the same process as the caller. The
sigev_notify_thread_id field specifies a kernel thread ID,
that is, the value returned by clone(2) or gettid(2). This
flag is intended only for use by threading libraries.
The thread ID (threadid in the question code) needs to be a kernel thread ID. That ID can be obtained with gettid.
i have the following case
void foo() {
printf("hi\n");
while(1);
}
int main(void)
{
struct sigaction temp;
temp.sa_handler = &foo;
sigfillset(&temp.sa_mask);
sigdelset(&temp.sa_mask, SIGVTALRM);
sigdelset(&temp.sa_mask, SIGINT );
sigaction(SIGVTALRM, &temp, NULL);
struct itimerval tv;
tv.it_value.tv_sec = 2; /* first time interval, seconds part */
tv.it_value.tv_usec = 0; /* first time interval, microseconds part */
tv.it_interval.tv_sec = 2; /* following time intervals, seconds part */
tv.it_interval.tv_usec = 0; /* following time intervals, microseconds part */
if (setitimer(ITIMER_VIRTUAL, &tv, NULL)){
perror(NULL);
}
while(1);
return 0;
}
all I want is that every 2 seconds foo will be called (foo actually does some other stuff other than while(1), just assume foo run takes more than 2 seconds), after 2 seconds foo is indeed called but then no other call is made untill foo returns. I tried playing with the signal masks (hence the sigfillset) but also when simply calling signal(SIGVTALRM, foo) no changes are made in the result. I also tried having the itimerval and the sigactions variables declared outside main and it didn't quite affect anything.
is the thing I'm trying to do even possible?
thanks!
reference: <http://www.gnu.org/software/libc/manual/html_node/Signals-in-Handler.html>
24.4.4 Signals Arriving While a Handler Runs
What happens if another signal arrives while your signal handler function is running?
When the handler for a particular signal is invoked, that signal is automatically blocked until the handler returns. That means that if two signals of the same kind arrive close together, the second one will be held until the first has been handled. (The handler can explicitly unblock the signal using sigprocmask, if you want to allow more signals of this type to arrive; see Process Signal Mask.)
However, your handler can still be interrupted by delivery of another kind of signal. To avoid this, you can use the sa_mask member of the action structure passed to sigaction to explicitly specify which signals should be blocked while the signal handler runs. These signals are in addition to the signal for which the handler was invoked, and any other signals that are normally blocked by the process. See Blocking for Handler.
When the handler returns, the set of blocked signals is restored to the value it had before the handler ran. So using sigprocmask inside the handler only affects what signals can arrive during the execution of the handler itself, not what signals can arrive once the handler returns.
Portability Note: Always use sigaction to establish a handler for a signal that you expect to receive asynchronously, if you want your program to work properly on System V Unix. On this system, the handling of a signal whose handler was established with signal automatically sets the signal’s action back to SIG_DFL, and the handler must re-establish itself each time it runs. This practice, while inconvenient, does work when signals cannot arrive in succession. However, if another signal can arrive right away, it may arrive before the handler can re-establish itself. Then the second signal would receive the default handling, which could terminate the process.
reference:<http://www.gnu.org/software/libc/manual/html_node/Process-Signal-Mask.html#Process-Signal-Mask>
24.7.3 Process Signal Mask
The collection of signals that are currently blocked is called the signal mask. Each process has its own signal mask. When you create a new process (see Creating a Process), it inherits its parent’s mask. You can block or unblock signals with total flexibility by modifying the signal mask.
The prototype for the sigprocmask function is in signal.h.
Note that you must not use sigprocmask in multi-threaded processes, because each thread has its own signal mask and there is no single process signal mask. According to POSIX, the behavior of sigprocmask in a multi-threaded process is “unspecified”. Instead, use pthread_sigmask.
Function: int sigprocmask (int how, const sigset_t *restrict set, sigset_t *restrict oldset)
Preliminary: | MT-Unsafe race:sigprocmask/bsd(SIG_UNBLOCK) | AS-Unsafe lock/hurd | AC-Unsafe lock/hurd | See POSIX Safety Concepts.
The sigprocmask function is used to examine or change the calling process’s signal mask. The how argument determines how the signal mask is changed, and must be one of the following values:
SIG_BLOCK
Block the signals in set—add them to the existing mask. In other words, the new mask is the union of the existing mask and set.
SIG_UNBLOCK
Unblock the signals in set—remove them from the existing mask.
SIG_SETMASK
Use set for the mask; ignore the previous value of the mask.
The last argument, oldset, is used to return information about the old process signal mask. If you just want to change the mask without looking at it, pass a null pointer as the oldset argument. Similarly, if you want to know what’s in the mask without changing it, pass a null pointer for set (in this case the how argument is not significant). The oldset argument is often used to remember the previous signal mask in order to restore it later. (Since the signal mask is inherited over fork and exec calls, you can’t predict what its contents are when your program starts running.)
If invoking sigprocmask causes any pending signals to be unblocked, at least one of those signals is delivered to the process before sigprocmask returns. The order in which pending signals are delivered is not specified, but you can control the order explicitly by making multiple sigprocmask calls to unblock various signals one at a time.
The sigprocmask function returns 0 if successful, and -1 to indicate an error. The following errno error conditions are defined for this function:
EINVAL
The how argument is invalid.
You can’t block the SIGKILL and SIGSTOP signals, but if the signal set includes these, sigprocmask just ignores them instead of returning an error status.
Remember, too, that blocking program error signals such as SIGFPE leads to undesirable results for signals generated by an actual program error (as opposed to signals sent with raise or kill). This is because your program may be too broken to be able to continue executing to a point where the signal is unblocked again. See Program Error Signals.
I know that this has been answered and accepted already but I made tiny changes to the OP's question as follows in accordance with my comments and had a successful result (foo being called every 2 seconds, ad infinitum)
Note that addition of the memset of the temp variable and the changing from SIGVTALRM to SIGALRM.
#include <stdio.h>
#include <sys/time.h>
void foo() {
printf("hi\n");
}
int main(int argc, char **argv)
{
struct sigaction temp;
memset(&temp, 0, sizeof(temp));
temp.sa_handler = &foo;
sigfillset(&temp.sa_mask);
sigdelset(&temp.sa_mask, SIGALRM);
sigdelset(&temp.sa_mask, SIGINT );
sigaction(SIGALRM, &temp, NULL);
struct itimerval tv;
tv.it_value.tv_sec = 2; /* first time interval, seconds part */
tv.it_value.tv_usec = 0; /* first time interval, microseconds part */
tv.it_interval.tv_sec = 2; /* following time intervals, seconds part */
tv.it_interval.tv_usec = 0; /* following time intervals, microseconds part */
if (setitimer(ITIMER_REAL, &tv, NULL)){
fprintf (stderr, "cannot start timer\n");
perror(NULL);
}
while(1) {
fprintf (stdout, "sleep 1\n");
sleep (1);
}
return 0;
}
I've got the following function that gets called from a pthread_create. This function does some work, sets a timer, does some other work and then waits for the timer to expire before doing the loop again. However, on the first run of the timer, after it expires the program quits and I'm not totally sure why. It should never leave the infinite while loop. The main thread accesses nothing from this thread and vice versa (for now).
My guess is I might not have something setup correctly with the thread, or the timer is not calling the handler function correctly. Perhaps changing the IDLE global variable from the thread causes a problem.
I would like to call the handler without signals, hence the use of SIGEV_THREAD_ID. I'm using the SIGUSRx signals in the main thread anyway. Any thoughts about what I've started here what could be wrong?
#ifndef sigev_notify_thread_id
#define sigev_notify_thread_id _sigev_un._tid
#endif
volatile sig_atomic_t IDLE = 0;
timer_t timer_id;
struct sigevent sev;
void handler() {
printf("Timer expired.\n");
IDLE = 0;
}
void *thread_worker() {
struct itimerspec ts;
/* setup the handler for timer event */
memset (&sev, 0, sizeof(struct sigevent));
sev.sigev_notify = SIGEV_THREAD_ID;
sev.sigev_value.sival_ptr = NULL;
sev.sigev_notify_function = handler;
sev.sigev_notify_attributes = NULL;
sev.sigev_signo = SIGRTMIN + 1;
sev.sigev_notify_thread_id = syscall(SYS_gettid);
/* setup "idle" timer */
ts.it_value.tv_sec = 55;
ts.it_value.tv_nsec = 0;
ts.it_interval.tv_sec = 0;
ts.it_interval.tv_nsec = 0;
if (timer_create(0, &sev, &timer_id) == -1) {
printf("timer_create failed: %d: %s\n", errno, strerror(errno));
exit(3);
}
while (1) {
// do work here before timer gets started that takes 5 seconds
while (IDLE); /* wait here until timer_id expires */
/* setup timer */
if (timer_settime(timer_id, 0, &ts, NULL) == -1) {
printf("timer_settime failed: %d\n", errno);
exit(3);
}
IDLE = 1;
// do work here while timer is running but that does not take 10 seconds
}
}
As far as I can tell, you haven't installed a signal handler for SIGUSR1, so by the default action it kills the process when it's acted upon.
In any case, the whole thing strikes me as extraordinarily bad design:
The while loop will give you 100% cpu load while waiting for the timer to expire.
This is not the way you use SIGEV_THREAD_ID, and in fact SIGEV_THREAD_ID isn't really setup to be usable by applications. Rather it's for the libc to use internally for implementing SIGEV_THREAD.
You really don't want to be using signals. They're messy.
If you have threads, why aren't you just calling clock_nanosleep in a loop? Timers are mainly useful when you can't do this, e.g. when you can't use threads.
I work on an embedded system with eCos:
I have 2 threads within the same process and 1 semaphore.
Thread A initializes a semaphore to 0 so that the 1st attempt to take it will block.
Thread A sends a command to Thread B, providing a callback.
Thread A waits on semaphore with sem_timedwait
Thread B process the command and increments the semaphore
Thread A should be woken up but is still blocked
Here is the code:
Thread A
static sem_t semaphore;
void callback()
{
// Do some stuff
int ret = sem_post(&semaphore);
// print confirmation message
}
void foo()
{
int ret = sem_init(&semaphore, 0, 0);
if(ret != 0)
{
// print errno
}
struct timespec ts;
clock_gettime(CLOCK_REALTIME,&ts); // Get current date
ts.tv_sec += 2; // Add 2s for the deadline
send_command_to_thread_B(&callback);
ret = sem_timedwait(&semaphore, &ts);
if(ret != 0)
{
// print errno
}
// print waking up message
}
What is in Thread B is not relevant.
For debug I tried the following:
Using sem_wait rather than sem_timedwait works: Thread A is blocked, then unlocked after the callback. But I don't want to use it because if there is a failure in the callback process that prevent the semaphore to be incremented, Thread A will wait forever.
If I don't add the 2s to the timespec struct, sem_timedwait returns immediatly and errno is set to ETIMEDOUT (seems legit). The callback is called but it is too late for Thread A.
I put traces in the callback call to ensure that the semaphore is indeed incremented from 0 to 1: all the process is done, the callback exits but Thread A is still blocked.
Do you guys have any clue ? Am I missing something ?
Ok so actually everything is fine with this code, the issue was elsewhere : I had a re-entrance problem that caused a deadlock.
Moral: Carefully protect your resources and addresses in a multi-thread context
I want to use the select() function to wait for 1 second, as my program uses signals to control stuff, so sleep() would return prematurely. The weird thing is that when using select() it also returns prematurely.
I am calling select like this
struct timeval timeout;
timeout.tv_sec = 10;
timeout.tv_usec = 1000000;
select (0 ,NULL, NULL, NULL, &timeout);
but whenever a signal arrives, it returns (I am using a nano second timer for the signal)
Anyone knows why?
Try something like this:
struct timespec timeout;
timeout.tv_sec = 10;
timeout.tv_nsec = 0;
while (nanosleep(&timeout, &timeout) && errno == EINTR);
The "remaining time" pointer to nanosleep will take care of letting you restart the sleep with the necessary amount of remaining time if it gets interrupted.
man 7 signal says:
Interruption of System Calls and Library Functions by Signal Handlers
If a signal handler is invoked while a system call or library
function call is blocked, then
either:
* the call is automatically restarted after the signal handler
returns; or
* the call fails with the error EINTR.
Which of these two behaviors occurs depends on the interface and
whether or not the signal handler
was established using the SA_RESTART flag (see sigaction(2)).
The details vary across UNIX sys‐
tems; below, the details for Linux.
If a blocked call to one of the following interfaces is
interrupted by a signal handler, then
the
call will be automatically restarted after the signal handler
returns if the SA_RESTART flag was
used; otherwise the call will fail with the error EINTR
Generally, checking if the return value is -1 and errno == EINTR and then re-calling the function is the right way to correct for this.