Signal Handler for SIGINT - c

I am working on the following code. The program should be able to handle SIGINT with sigaction. So far, it's almost done, but I have come along two problems. The first problem is the program should print "Shutting down" and exit with status 1 if it receives 3 signals within 3 seconds.
The second problem is I am using gettimeofday and struct timeval to get the time in seconds regarding to the arrival times of the signals, but I failed here as well. When I tried it out, I got stuck in an infinite loop, even thought I pressed ctrl + C 3 times within 3 seconds. Also, the resulting seconds are quite big numbers.
I hope someone could help me to get these two problems done. Here's the code
int timeBegin = 0;
void sig_handler(int signo) {
(void) signo;
struct timeval t;
gettimeofday(&t, NULL);
int timeEnd = t.tv_sec + t.tv_usec;
printf("Received Signal\n");
int result = timeEnd - timeBegin;
if(check if under 3 seconds) { // How to deal with these two problems?
printf("Shutting down\n");
exit(1);
}
timeBegin = timeEnd // EDIT: setting the time new, each time when a signal arrives. Is that somehow helpful?
}
int main() {
struct sigaction act;
act.sa_handler = &sig_handler;
sigaction(SIGINT, &act, NULL);
for( ;; ) {
sleep(1);
}
return 0;
}

int timeEnd = t.tv_sec + t.tv_usec;
That won't work because tv_sec and tv_usec are different orders of magnitude. If you want microsecond accuracy, you'll have to store the value in a larger type (e.g. int64_t) and convert the seconds to microseconds.
if(check if under 3 seconds) { // How to deal with these two problems?
Well, what have you tried? You have several signals arriving at different times, you need to keep some state about them to know if all arrived within 3 seconds of each other.

Related

how to set multiple Alarms using "setitimer()" function call

I have a requirement to set more than one interval-timers (alarms of same type : ITIMER_REAL) in the same process. so I used setitimer() system call to create 3 alarms with each timer having separate structures to hold time interval values. when any timer expires it will give a signal SIGALRM to the calling process, but i couldn't find which timer among three has given the signal and I don't even know whether all the timers are running or not. Is there any way to find which timer has given the signal...
Thank you.
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
void timer_handler (int signum)
{
static int count = 0;
printf ("timer1 expired %d times\n", ++count);
}
int main ()
{
int m = 0;
struct sigaction sa;
struct itimerval timer1, timer2, timer3;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timer_handler;
sigaction (SIGALRM/*SIGVTALRM*/, &sa, NULL);
timer1.it_value.tv_sec = 1;
timer1.it_value.tv_usec = 0;
timer1.it_interval.tv_sec = 5;
timer1.it_interval.tv_usec = 0;
timer2.it_value.tv_sec = 2;
timer2.it_value.tv_usec = 0/* 900000*/;
timer2.it_interval.tv_sec = 5;
timer2.it_interval.tv_usec = 0/*900000*/;
timer3.it_value.tv_sec = 3;
timer3.it_value.tv_usec = 0/* 900000*/;
timer3.it_interval.tv_sec = 5;
timer3.it_interval.tv_usec = 0/*900000*/;
setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer1, NULL);
setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer2, NULL);
setitimer (ITIMER_REAL/*ITIMER_VIRTUAL*/, &timer3, NULL);
while (1)
{
//printf("\nin main %d",m++);
//sleep(1);
}
}
No, you only have one ITIMER_REAL timer per process. Using setitimer multiple times overwrites the previous value, see man setitimer
A process has only one of each of the three types of timers.
You can also see this, when you modify the intervals in your example code
timer1.it_interval.tv_sec = 1;
timer2.it_interval.tv_sec = 2;
and using nanosleep instead of sleep, because it might interfere with SIGALRM.
Now running the code, you will see only 5 second intervals.
You can also retrieve the previous set value by providing a second struct itimerval
struct itimerval old1, old2, old3;
setitimer(ITIMER_REAL, &timer1, &old1);
setitimer(ITIMER_REAL, &timer2, &old2);
setitimer(ITIMER_REAL, &timer3, &old3);
old1 will contain zero values, because it is the first time you use setitimer. old2 contains it_interval = 1 sec, and old3 contains it_interval = 2 sec. The it_values will be different, depending on how much time elapsed between the calls to setitimer.
So, if you need multiple timers, you need to do some bookkeeping. Each time a timer expires, you must calculate which timer is next and call setitimer accordingly.
As an alternative, you may look into POSIX timers. This allows to create multiple timers
A program may create multiple interval timers using timer_create().
and also pass some id to the handler via sigevent. Although the example at the end of the man page looks a bit more involved.
If I understand your question right you want to know the status of the different timers.
In the reference a getitimer function avalable:
The function getitimer() fills the structure pointed to by curr_value
with the current setting for the timer specified by which (one of
ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF). The element it_value is
set to the amount of time remaining on the timer, or zero if the timer
is disabled. Similarly, it_interval is set to the reset value.
You can find the full reference here Link
Hope that helps

Sending a variable changed by a signal to a process created by exec in the child process.[C]

So I'm creating a signal handler to modify the speed at which output is printed to the screen. The output is done by a process that prints to another terminal open while still allowing the user to put in input such as '+' to increase the speed its read and '-' to decrease the speed.
The code looks something like this.
static state* start_button(void)
{
state *destination;
pid_t pid;
pid = fork();
switch(pid)
{
case -1:
destination = &ready;
break;
case 0:
execl("./outputTerminal",
"outputTerminal",file_number,"/dev/ttys001",NULL);
break;
default:
destination = &going;
break;
}
return destination;
}
In the going state(going.c) my thought process was to create volatile variables seconds and nanoseconds and use those variables to update the nanosleep() function that outputTerminal is using to read the lines 1 line at a time like so in the code snippet below. Is this possible? This is a homework question btw. I have all the functions working like they are supposed to I just need to figure out how to send the variables changed by the signal over to that process. I tried doing kill(baby_pid,SIGUSR1) in the going state after I set the signal handler because I saved the pid but that just kills the process outputTerminal for some reason.
//going.c
volatile sig_atomic_t seconds;
volatile sig_atomic_t nanoseconds; //Update these in the going state
//Then pass them to the process outputTerminal like so
//outputTerminal.c
struct timespec tm1,tm2;
tm1.tv_sec = seconds;
tm2.tv_nsec = nanoseconds;
nanosleep(&tm1,&tm2);
This is my signal handler
static void speed_handler(int signal)
{
long max_nano = 1000000000L;
long incrementer = 250000000L;
if(speed_control == 0)
{
if(nanoseconds == 0L && seconds > 0)
{
seconds -= 1;
nanoseconds = max_nano;
}
if(nanoseconds != 0L)
nanoseconds -= incrementer;
}
if(speed_control == 1)
{
nanoseconds += incrementer;
if(nanoseconds >= max_nano)
{
nanoseconds = 0L;
seconds += 1;
}
}
}
What you're looking for is called IPC, short for Inter-process Communication and there are many ways to do what you want.
Your approach doesn't work because your processes have distinct address spaces so changing a variable in one has no effect on the other.
A few ways in which you could communicate information from one process to another:
Share memory between processes (using mmap with MAP_SHARED)
Send extra information using signals (look up sigqueue and sigval. Or maybe check this old answer https://stackoverflow.com/a/7270506)
Use a pipe
Or a message queue
There are quite a few more mechanisms but this should get you started.

Terminating main thread after a certain time in C

I have created two array of threads using POSIX thread.There are two thread functions student and teacher(I have not shown them here). My sample program is given below. I want to make a time limit(say 10 sec) after which the main thread will automatically exit no matter if the corresponding threads have completed or not. How will I do that?
Sample code fragment:
int main(void)
{
pthread_t thread1[25];
pthread_t thread2[6];
int i;
int id1[25]; //for students
int id2[6]; //for teachers
for(i=0;i<25;i++)
{
id1[i]=i;
id2[i]=i;
pthread_create(&thread1[i],NULL,student,(void*)&id1[i] );
if(i<6)
{
pthread_create(&thread2[i],NULL,teacher,(void*)&id2[i]);
}
}
for (i=0;i<25;i++)
{
pthread_join(thread1[i],NULL);
if(i<6)
{
pthread_join(thread2[i],NULL);
}
}
return 0;
}
What additional things will I have to add to the above code to terminate the main thread after a certain time? (say: 10 seconds)
what you need is pthread timed join. See the snippet below
struct timespec
{
time_t tv_sec; /* sec */
long tv_nsec; /* nsec */
};
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == -1)
{
printf("ERROR\n");
}
ts.tv_sec += 10; //10 seconds
int st = pthread_timedjoin_np(thread, NULL, &ts); //only wait for 10 seconds
if (st != 0)
{
printf("ERROR\n");
}
For additional info refer the man page http://man7.org/linux/man-pages/man3/pthread_tryjoin_np.3.html
If you just want the whole process to be terminated after 10 seconds of waiting time, you just have to replace the whole for-loop with your pthread_join calls by a suitable sleep function. You could use nanosleep, clock_nanosleep, thrd_sleep or just
sleep(10);
After that your main function would go out of scope and terminate the process.
Beware, all these functions are sensible to signals that arrive in the middle.
One way to do this is to create another thread which will sleep for 10 seconds, then call exit() (which will terminate the entire process):
void *watchdog(void *arg)
{
sigset_t all_sigs;
/* Block all signals in this thread, so that we do not have to
* worry about the sleep() being interrupted. */
sigfillset(&all_sigs);
sigprocmask(SIG_BLOCK, &all_sigs, NULL);
sleep(10);
exit(0);
return NULL; /* not reached */
}
Create this thread from the main thread after creating the other threads, and detach it:
pthread_create(&watchdog_thread, NULL, watchdog, NULL);
pthread_detach(watchdog_thread);
Now your process will end either when the main thread finishes after joining the other threads, or when the watchdog thread calls exit(), whichever happens first.

Trouble with Interval Timer

Our current project is based on extending more by including scroll. In order to do this, a timer interval has to be set for a certain period. The part I'm not sure about is where the loop for the alarm signal should be. All the examples I've seen have the timer values in the main, then explicitly call the signal handler via pause() in an infinite while loop.
My code is a bit different, since the functionality requirements go like
print first screen of text after getting terminal dimensions
print prompt
if prompt = space, print another screen of text //WORKS
if prompe = q, restore original terminal settings & quit program //WORKS
if prompt = ENTER, initialize scroll at 1 line every 2 seconds //DOESN'T WORK
if prompt == f/s, increase/decrease scroll speed by 20% //DOESN'T WORK
The read in buffer, file pointer and itimerval struct are all global variables to avoid passing as arguments through a chain of functions.
The main function of the program is
void processInput(FILE *fp){
void printLine(int); //prints a single line of text
signal(SIGPROF, printLine);
int c;
//print first screen of text, check for more text to display
info(); //print prompt at bottom of screen
FILE *fterm= fopen("/dev/tty", "r");
while ((c=getc(fterm)) != EOF){
if (c== '\n'){
setTimer(2);
//four more conditionals like this in basic similarity
}
}
My setTimer function has a base interval of 2 seconds, and changes that by plus/minus 20% based on f/s input from the user.
void setTimer(int direction){
int speed=2000000; //2 seconds
int change= 400000; //400 milliseconds, 20% of 2 seconds
if (direction == 1) //slow down by 20%
speed+= change;
if (direction == 0)
speed -= change;
timer.it_value.tv_sec=2;
timer.it_value.tv_usec=0;
timer.it_interval.tv_sec=0;
timer.it_interval.tv_usec= speed;
setitimer(ITIMER_PROF, &timer, NULL);
}
First question: should I use SIGALRM vs SIGPROF, and alter the ITIMER_XXXX variable accordingly?
Second, where should I put in the loop to trigger the signal? I tried
while(1)
pause();
in several of the conditionals, but it had the effect of stopping the execution and ignoring any input.
Without knowing the details of your requirements, couldn't you do this more easily using
select()?
Set your initial select timeout to 2 seconds and adjust according to f/s input, meanwhile if there is any standard input before the timeout you process it.
More or less valid general outline:
int retval;
fd_set rfds;
int input = fileno(fterm);
struct timeval tv, delay;
delay.tv_sec = 2;
delay.tv_usec = 0;
while (true)
{
FD_ZERO(&rfds);
FD_SET(input, &rfds);
tv.tv_sec = delay.tv_sec;
tv.tv_usec = delay.tv_usec;
retval = select(input + 1, &rfds, NULL, NULL, &tv);
if (retval == -1)
perror("select()");
else
if (retval)
{
if (FD_ISSET(input, &rfds))
{
command = readInput(...);
switch(command)
{
case 'q' ... cleanup & quit
case 's' ... calc 20% off delay values
case etc ...
case default...error handling
}
}
}
else //timeout
printLine();
}
Working with pause() is dangerous because it's not an atomic operation ... your program could be interrupted by the OS causing you to "lose" the arrival of a signal. Additionally, when pause() itself returns because of the arrival of a signal, it will simply call pause() again. That means you're going to have to-do all your work inside of a signal handler, which may not be the best thing, i.e., if you're inside the signal handler when the next signal goes off, you can end up with some unpredictable behavior if you haven't planned for that sort of event.
A better approach would be to-do the following:
1) Setup a signal mask that blocks SIGPROF at the start of your program.
2) Rather than using a signal handler to-do your heavy lifting, use sigwait(), and set it up with a sigset_t that contains a mask for SIGPROF.
3) Setup the main flow of your program the following way:
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGPROF);
sigprocmask(SIG_BLOCK, &sigset, NULL); //block the SIGPROF signal
//process your input
//if you need to, initialize your timer and set it to go off
while(SOME_FLAG_IS_TRUE) //maybe this loops forever ... depends on what you want?
{
sigwait(&sigset, &signal_num);
if (signal_num != SIGPROF)
continue;
//process input ...
//... setup new interval timer with correct timeout ...
//... repeat loop and/or exit loop or set flag to exit loop
}
That should always catch the signal from the interval timer since sigwait() will properly return after waiting for a signal to arrive to your process, and the SIGPROF signal is always blocked, meaning you can't "lose" signals ... instead at least one of them will be queued up and waiting for the next call to sigwait() to be detected just in case one arrives while you're processing something in your while-loop.
Hope this helps,
Jason

Issue in pausing the posix thread for specific time interval in c

I have to call one method in seperate thread (i am using posix thread)which updates some value after every 5 second for which have written below code.
void *threadEntry(void *)
{
while(1)
{
updateValue();//to update some values
usleep(5000000);//pause for 5 second
}
}
pthread_t thread1;
pthread_create(&thread1,NULL,threadEntry,NULL);
But this thread gets segmentation fault after 4-5 minutes .What can be reason?Is there any other way to pause the posix thread.(i am using linux)
On POSIX systems (which linux is) nanosleep is the right thing for such a sleep:
int nanosleep(const struct timespec *req, struct timespec *rem);
where req is your request an rem is the time remaining to sleep if your thread was interrupted prematurely.
The right thing to do is to use nanosleep, because usleep and sleep might mess with SIGALARM, while nanosleep was specifically designed with threads in mind :
struct timespec mytimeout = {
.tv_sec = 5,
.tv_usec = 0,
};
struct timespec remaining;
nanosleep(&mytimeout, &remaining);
My original answer was to use a select trick, but let's stop promoting bad code
Back to the root of the problem, how do you know your segmentation fault come from the sleeping code ?
Did you get a core dump you could backtrace ?

Resources