Lab Four (4) Signals, alarm , pause, kill, raise
See 'man 7 signal' for a list of all the signals
NAME
signal - ANSI C signal handling
SYNOPSIS
#include
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
DESCRIPTION
The signal() system call installs a new signal handler for
the signal with number signum. The signal handler is set
to sighandler which may be a user specified function, or
either SIG_IGN or SIG_DFL.
Upon arrival of a signal with number signum the following
happens. If the corresponding handler is set to SIG_IGN,
then the signal is ignored. If the handler is set to
SIG_DFL, then the default action associated to the signal
(see signal(7)) occurs. Finally, if the handler is set to
a function sighandler then first either the handler is
reset to SIG_DFL or an implementation-dependent blocking
of the signal is performed and next sighandler is called
with argument signum.
Using a signal handler function for a signal is called
"catching the signal". The signals SIGKILL and SIGSTOP
cannot be caught or ignored.
RETURN VALUE
The signal() function returns the previous value of the
signal handler, or SIG_ERR on error.
IMPORTANT NOTE:
What should the operating system do if a process receives
interupt (signal) X while it is in the middle of handling
interupt X? On some OS, it ignores the interupt until it
has finished the first interupt. The more recent Linux
versions do not do this, instead they immediately handle
the 2nd interupt but instead of doing the interupt function
handler they do the default behaviour of the interupt
(usually terminating the process). This can be a problem
if your program is not properly synchronized.
Program to demostrate the 'catching' or 'trapping' of the signal FPE
(divide-by-zero)
//by Nachum Danzig
#include
#include
static void sig_fpe(int signo) ;
int main(void)
{
int x = 0;
int y;
if (signal(SIGFPE, sig_fpe) == SIG_ERR)
perror("can't catch SIGFPE");
y= 7/x;
printf("hello");
return 1;
}
//our trap function
static void sig_fpe(int signo) /*argument is signal number*/
{
printf("You divided by zero, didn't you?\n");
raise(SIGALRM);
return;
}
Program to demostrate the 'catching' or 'trapping' of the signal crtl-c
//by Nachum Danzig
#include
#include
static void sig_interupt(int signo) ;
int main(void)
{
if (signal(SIGINT, sig_interupt) == SIG_ERR)
perror("can't catch SIGINT");
for( ; ; )
pause();//wait for any signal (only needed so the loop does not waste CPU time)
}
//our trap function
static void sig_interupt(int signo) /*argument is signal number*/
{
printf("received SIGINT, but I ain't quitin'\n");
return;
}
NAME
pause - wait for signal
SYNOPSIS
#include
int pause(void);
DESCRIPTION
The pause library function causes the invoking process (or thread) to
sleep until a signal is received that either terminates it or causes it
to call a signal-catching function.
RETURN VALUE
The pause function only returns when a signal was caught and the sig-
nal-catching function returned. In this case pause returns −1, and
errno is set to EINTR.
#include
#include
static void sig_usr(int signo) ;
int main(void)
{ int counter=0;
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
perror("can't catch SIGUSER1");
if (signal(SIGUSR2, sig_usr) == SIG_ERR)
perror("can't catch SIGUSER2");
for( ; ; )
{
printf("loop number: %d\n", ++counter);
pause();//wait for any signal
}
}
//one trap which handles two different interrupts
static void sig_usr(int signo) /*argument is signal number*/
{
if (signo == SIGUSR1)
printf("received SIGUSR1\n");
else if (signo == SIGUSR2)
printf("received SIGUSR2\n");
return;
}
NAME
alarm - set an alarm clock for delivery of a signal
SYNOPSIS
#include
unsigned int alarm(unsigned int seconds);
DESCRIPTION
alarm arranges for a SIGALRM signal to be delivered to the
process in seconds seconds.
If seconds is zero, no new alarm is scheduled.
In any event any previously set alarm is cancelled.
RETURN VALUE
alarm returns the number of seconds remaining until any
previously scheduled alarm was due to be delivered, or
zero if there was no previously scheduled alarm.
An Example which demonstrates having a process sleep
until the ALRM signal is registered
//by Nachum Danzig
#include
#include
#include
static void sig_alarm(int signo) ;
unsigned int mysleep(unsigned int nsecs );
//#define SIG_ERR (void (*)())-1
int main(void)
{ int unslept;
for( ; ; )
{
printf("go to sleep.\n");
unslept=mysleep(2);
printf("%s \n", unslept);
}
}
static void sig_alarm(int signo) /*argument is signal number*/
{
return;//do nothing, just return to wake up the pause
}
unsigned int mysleep(unsigned int nsecs )
{
if (signal(SIGALRM, sig_alarm) == SIG_ERR)
return(nsecs);
alarm(nsecs);//start timer
pause(); //next caught signal wakes us up
return(alarm(0)); //turn off timer, return unslept time
}
NAME
kill - send signal to a process
SYNOPSIS
#include
#include
int kill(pid_t pid, int sig);
DESCRIPTION
The kill system call can be used to send any signal to any process
group or process.
If pid is positive, then signal sig is sent to pid.
If pid equals 0, then sig is sent to every process in the process group
of the current process.
If pid equals -1, then sig is sent to every process except for process
1 (init), but see below.
If pid is less than -1, then sig is sent to every process in the process group pid.
If sig is 0, then no signal is sent, but error checking is still
performed.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is
set appropriately.
IMPORTANT NOTE: If the signo argument is 0, then the normal error checking is
performed by kill, but no signal is sent. This is a way to determine if a
specific process exists. If we send the process the null signal but the
process does not exist, kill will return -1 and errno is set to ESRCH.
(Because of the recylcing of PID's in UNIX, the PID maybe be in use by
another process, so you can not be 100% sure the process you intend
still exists)
NAME
raise - send a signal to the current process
SYNOPSIS
#include
int raise(int sig);
DESCRIPTION
The raise() function sends a signal to the current process. It is
equivalent to
kill(getpid(), sig);
RETURN VALUE
0 on success, nonzero for failure.
An example demonstraing the sending of a signal to
a child process.
//by Nachum Danzig
#include
#include
#include
static void sig_usr(int signo) ;
int counter = 0;
int main(void)
{
int i, error, status;
pid_t child1;
error = kill(999999,0);//demonstrate checking if process exists
printf("error: %d\n", error);
if (signal(SIGUSR1, sig_usr) == SIG_ERR)
perror("can't catch SIGUSER1");
child1=fork();
if(0==child1)
{
printf("child is running\n");
for(;;)
{
pause();//some code
}
}
else
{
//we are Dad
for( i=0;i<100000000;i++);//avoid race condition
for(counter=0;counter<3;counter++)
{
kill(child1, SIGUSR1);//the real point of this example, send signal to child
}
kill(child1, 9);//cleanup, really KILL the child (KILL==9) (but child will still be a zombie)
wait(&status);//kill zombie child (see note on 'zombies' in Lab1)
error = kill(child1,0);//make sure child process no longer exists
printf("error: %d\n", error);
}
}
static void sig_usr(int signo) /*argument is signal number*/
{
printf("child received SIGUSR1 by %d\n", getpid() );
}
Exercise 3
You are asked to create one pipe to be used as a communication exchange.
A parent process creates 3 child processes. It will signal which child is
to listen on the pipe at which time. The parent process will allow the
user to choose to which process he wants to send a message.
The user will be able to send a text message to any son he wants through
the pipe common to all processes. The user will be able to kill any child
he desires, and at any time. The program will keep running until the user kills
all the 3 child processes.
If user types 'quit' you must kill all children before exiting (otherwise they will
not die until the system comes down).
Do the same if the user types control-c (note: use a trap on control-c).
Also the father may send signals other than -KILL (-9) to the children.
Implement 3 such signals of your choice.
'man 7 signal' will list for you all the signals.
Sample input and output:
>
> 1 hello
son 1: hello
> 3 hello
son 3: hello
> 1 kill -KILL
father: son 1 terminated.
> 1 hello
father: son 1 no longer alive.
> 3 hello
son 3: hello
> 3 kill -KILL
father: son 3 terminated.
> 2 kill -KILL
father: all sons died. Bye.
>
>
Partial answer to problem.
© Ari Cirota, Nachum Danzig and Erick Fredj