Solved

How do I use signals, interrupts and alarms in this program?

Posted on 2007-11-14
8
470 Views
Last Modified: 2010-05-18
I am working on a school lab but I am stuck with understanding exactly how to handle signals.

In the lab I'm supposed to set an alarm based on the duration from the argument list. During the duration of the alarm, anytime I hit (Ctrl + C) a message should pop up saying "Interrupts disabled". I need to handle the alarm signal so when it goes off I will execute a command also from the argument list. The command should be a single word command such as "ls" which lists all directories or "pwd" which lists the present working directory. Also after the alarm goes off I need to reset the interrupts to the default which enables (Ctrl + C) to quit the process whenever pressed.

At the bottom is the code I have so far. My problem is trying to set the interrupt to default after the alarm goes off. I thought maybe in the alarm_hanlder I could reset it to default but that doesn't seem to work.
If I take the line ---> signal(SIGINT, interrupt);   out of the while loop I can only use the interrupt once. The second time I press (Ctrl+c) it will actually quit the process.

The next thing that puzzles me is even though the alarm_handler handles the alarm how can I have the alarm_handler execute the command inputed by the user?
The user input is : a.out 4 ls    <-   argv[1] is "4" which is the duration of alarm and argv[2] is "ls" which is the command to be executed.
I know I need to use execlp(argv[1], argv[2],  "NULL");   but I am not sure exactly how to use it in the alarm_handler because I need to pass the values argv[1] and argv[2] to the handler some how? or is the only way to do this by declaring global variables and make these values equal to argv[1] and argv[2]?
In order to not loss my current process I need to create a child process to run execlp();
Perhaps I am doing this completely wrong and I should have the execlp() in main(); although I would be very confused on how that would work?

Thanks in advance.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void alarm_handler(int);
void interrupt(int);
     
void alarm_handler(int dummy){
      printf("I received an alarm %d\n", dummy);
     signal(SIGINT,SIG_DFL);
      /* if ( fork() == 0 )
              execlp(argv[1], argv[2], "NULL");
      */
}
         
void interrupt(int signal){
    printf("Interrupt disabled until delayed command is executed\n");
}

int main(int argc, char *argv[]){

     int x = atoi( argv[1] );

     signal(SIGALRM, alarm_handler);//install handler
     alarm(x);

     while(1){
         signal(SIGINT, interrupt);
         sleep(1);
     }

}

 
0
Comment
Question by:stockhouse50
  • 4
  • 2
  • 2
8 Comments
 
LVL 11

Assisted Solution

by:cup
cup earned 50 total points
Comment Utility
You're almost there but first I'll answer your questions.

The only way I've found of passing data to a signal handler is by global variables.  You can fake globals by using  class but it is still global to the class so you may as well call it a global.

The parameter that the handler receives is the signal id.  You can have one handler for a variety of signals so you need to know which signal you're recieving.

Now - the code.  First setup all the signal handlers.  Don't do it in a loop.

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>

void alarm_handler(int);
void interrupt(int);
     
char command[80];
void alarm_handler(int dummy){
      printf("I received an alarm %d\n", dummy);
     signal(SIGINT,SIG_DFL);
      execlp(command, "", NULL);
}
         
void interrupt(int signal){
    printf("Interrupt disabled until delayed command is executed\n");
}

int main(int argc, char *argv[]){

     int x = atoi( argv[1] );
     // Make a local copy of the argument
     strcpy (command, argv[2]);

     signal(SIGALRM, alarm_handler);//install handler
     // put the handler here: not in the loop
     signal(SIGINT, interrupt);

     alarm(x);

     while(1){
         sleep(1);
     }

     // missing
     return 0;
}
0
 

Author Comment

by:stockhouse50
Comment Utility
Hi, thanks for the reply. The problem that is still there is how signal(SIGINT, interrupt) and the interrupt handler are set up. The first time I hit (CTRL+C) I will receive the message "Interrupt disabled until delayed command is executed" but the second I hit (CTRL + C) the process will actually quit. How do I prevent the process from quiting before the alarm goes off no matter how many times I hit CTRL+C?

Also, how do I enable CTRL+C to work after the alarm goes off? I am not sure if signal(SIGINT,SIG_DFL); actually works in the alarm handler.

Thank you.
0
 

Author Comment

by:stockhouse50
Comment Utility
Actually I think signal(SIGINT,SIG_DFL); does work because I took out the execlp(); line to test if I could exit out of the loop in main() after the alarm goes off.  

However, I am still having the problem with CTRL+C only giving me the interrupt message once. If I hit Ctrl+C more than once anytime before the alarm goes off the process will quit. When I tested to see if signal(SIGINT,SIG_DFL); actually enabled CTRL+C I waited for the alarm to go off because I pressed CTRL+C because of the issue above.

Thanks again for the help.
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 450 total points
Comment Utility
SIG_DFL is the default handler which will terminate the program. So, if you do :

        signal(SIGINT, SIG_DFL);

you're effectively setting the default behavior back. But I'm sure you knew that, since you were using it correctly.

However, you have a problem with the implementation of your SIGINT handler. You have to re-set the handler whenever it's executed, or it will revert back to default behavior :

        void interrupt(int sig) {
            signal(SIGINT, interrupt);
            printf("Interrupt disabled until delayed command is executed\n");
        }

Also, a note : you shouldn't set the interrupt handler inside the infinite while loop. Rather set it before the while loop :

        signal(SIGINT, interrupt);
        while(1){
            sleep(1);
        }
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 

Author Comment

by:stockhouse50
Comment Utility
Hi, thanks for the help.
I tried doing exactly what you said but I now get this error when compiling the program.
 "labalarm.c", line 19: function designator is not of function type
"labalarm.c", line 41: warning: statement not reached
cc: acomp failed for labalarm.c

Line 19 refers to the  signal(SIGINT, interrupt);  line inside the interrupt hanlder.
I ran the program even though I had the above errors and it still does the exact same thing.

This is the output when I run it:
>a.out 6
Inside loop
Inside loop
^CInterrupt disabled until delayed command is executed
Inside loop
^C
>
 
Basically, after I hit CTRL+C  a second time the program once again exits.
I am sure exactly what the error message  '"labalarm.c", line 19: function designator is not of function type' means but how do I get around this?
Thanks again.

This is what my codes looks like:

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>

void alarm_handler(int);
void interrupt(int);

//char command[80];
void alarm_handler(int dummy){
      printf("I received an alarm %d\n", dummy);
      signal(SIGINT,SIG_DFL);
      //execlp(command, "", NULL);
}

void interrupt(int signal){
    signal(SIGINT, interrupt);
    printf("Interrupt disabled until delayed command is executed\n");
}

int main(int argc, char *argv[]){

     int x = atoi( argv[1] );
     // Make a local copy of the argument
    // strcpy (command, argv[2]);

     signal(SIGALRM, alarm_handler);//install handler

     alarm(x);

     signal(SIGINT, interrupt);

     while(1){
           printf("Inside loop\n");
         sleep(1);
     }
 
     return 0;
}
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
       void interrupt(int signal){

needs to be :

        void interrupt(int sig){

name clash between the parameter and the function ;)
0
 

Author Closing Comment

by:stockhouse50
Comment Utility
Cup helped partially on the question.
0
 
LVL 11

Expert Comment

by:cup
Comment Utility
I've been off the Unix circuit for some time.  I don't know whether people still use signal or not.  I thought it had been replaced by sigset about 12 years ago.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now