![Page 1: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/1.jpg)
Signals and Signal Handling
![Page 2: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/2.jpg)
Signals
A predefined message sent between two processes or from the kernel to a process, or by a user to a process
A software version of a hardware interrupt
It is a primitive form of interprocess communication
Signals are asynchronous
A process may receive a signal at any time during its execution
It must be prepared to respond to the signal at that time
Most are assigned an integer value (starting with 1) and a symbolic name
SIGKILL 9 /* Kill, unblockable (POSIX). */
You can see all the defined signals by executing the command man signal.h
![Page 3: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/3.jpg)
Signals Users send signals
with the keyboard
^c SIGINT 2 /* Interrupt */
To see the mappings of your keystrokes, enter the command stty -a
The kill command utility
kill [-signal] pid
The default signal sent is SIGTERM (15)
You may use either the integer value or the symbolic name of the signal
If after using kill pid, the process doesn't terminate, then use kill -9 pid
The kill( ) system call
![Page 4: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/4.jpg)
Signals
Each signal type has associated with it an action which the kernel will perform on behalf of a process when the process is sent that signal
Process can Perform the default action for that signal, such as
Terminate the process Suspend the process but don't terminate it
Ignore the signal The process will be unaware that the signal has occured Two signals cannot be ignored
– SIGKILL - Terminates a process – SIGSTOP - suspends a process
Catch and handle the signal Execute a pre-arranged signal handler A process can register a special signal-handling function It will be called when the signal is received by the process
![Page 5: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/5.jpg)
kill() system call
kill() system call: send any signal to a process group or process int kill(pid_t pid, int sig); sig is the signal to send (either integer value or symbolic name) pid specifies where to send the signal pid > 0 :The signal is sent to the process whose PID is pid pid = 0 :The signal is sent to all processes whose GID is the same as
the GID of the sender pid = -1 :The signal is sent to all processes that the current process may
send signals to If superuser: The signal is sent to all processes except init (PID 1)
sig = 0 No signal is actually sent, but all error checking is performed This can be used to see if process pid is still alive
RETURN VALUE On success (at least one signal was sent), zero is returned On error, -1 is returned, and errno is set appropriately
![Page 6: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/6.jpg)
Example
See kill_ex.c on webpage under Code Output
> ./kill_ex
child 1 is alive
child 2 is alive
child 1 is alive
child 2 is alive
child 1 is alive
child 2 is alive
Parent is about to suspend child 1
child 2 is alive
child 2 is alive
child 2 is alive
Parent is about to resume child 1
child 1 is alive
child 2 is alive
child 1 is alive
child 2 is alive
child 1 is alive
child 2 is alive
Parent is about to terminate both children
![Page 7: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/7.jpg)
alarm()
alarm( ) system call Each process has an alarm clock timer associated with it which it can use to
send itself SIGALRM signals
unsigned int alarm(unsigned int seconds); E.g. alarm(3) means send the calling process a SIGALRM signal 3
seconds later
If seconds is 0, any currently scheduled alarm is switched off
When alarm( ) is called, any previously scheduled alarms are cancelled 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 Include <unistd.h>
![Page 8: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/8.jpg)
pause()
pause( ) library function
Suspends the calling process until it receives a signal
The signal must be one that is not currently set to be ignored by the calling process
If the signal is caught and doesn't cause termination
-1 is returned
errno is set to EINTR
If the signal causes termination of the calling process
pause( ) does not return
![Page 9: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/9.jpg)
Example
alarm(3);
while(1) {
pause();
printf(“Signal Received”); // will be printed when SIGALRM is received.
}
![Page 10: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/10.jpg)
signal()
To ignore or catch a signal, we need to associate a signal-catching routine with that signal
signal( ) system call
sighandler_t signal(int signum, sighandler_t handler); Include <signal.h> signum is the value of the signal to be caught
You may also use the symbolic name for the signal It cannot be SIGKILL or SIGSTOP
handler is a pointer to a function This is the function (handler) that is executed if signal signum is received It may be a user-defined function Or SIG_DFL - the default action for the signal Or SIG_IGN - ignore this signal
The return value is the signal's previous handler
![Page 11: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/11.jpg)
Example: signal_ex.c
/* This program demonstrates ignoring the SIGINT. Follow the directions in the printf statements to play with the program*/
#include <stdio.h>#include <signal.h>
main(){ void (*oldHandler)(int); /* To hold old handler value */
printf("I can be Controled-C'ed\n"); sleep(3); oldHandler = signal(SIGINT, SIG_IGN); /* Ignore Control-C */ printf("I'm protected from Control-C now\n"); sleep(3); signal(SIGINT, oldHandler); /* Restore old handler */ printf("I can be Control-C'ed again\n"); sleep(3); printf("Bye!\n");}
![Page 12: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/12.jpg)
signal_ex.c
The line void (*oldHandler)(int); declares oldHandler to be a function that takes one int as an argument and returns a void pointer
Output:
> ./a.out
I can be Controled-C'ed
^C
> ./a.out
I can be Controled-C'ed
I'm protected from Control-C now
^CI can be Control-C'ed again
^C
>
![Page 13: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/13.jpg)
User-defined signal handlers
Use the handler to execute any code that you want when the signal is received
Usually the first line in a hander is another signal( ) statement
This reestablishes the connection between the handler and the signal
This is necessary because most signals are reset to take their default action after being caught and before executing the handler
If you don't immediately execute another signal( ) statement, then you can't catch another signal of the same type
Note that there is a small time frame where if a signal is received, the default action will occur
This is what makes signals an unreliable comminication mechanism
![Page 14: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/14.jpg)
Example: signal_ex2.c
/* This program demonstrates using a signal handler to catch SIGINT. Notice that the connection between the signal handler and signal is reestablished immediately up enter the handler.
To use: 1. As soon as it is running, hit multiple ^c's then <ret> 2. The signal handler counts the number of ^c's hit and prints out the total 3. The default signal handler is then reestablished 4. Hit another ^c and the program ends*/
![Page 15: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/15.jpg)
Example: signal_ex2.c #include <stdio.h>
#include <signal.h>#include <unistd.h>
int ctrl_c_count = 0;void (* old_handler)(int);void ctrl_c(int);
main(){ int c;
old_handler = signal(SIGINT, ctrl_c);
while ((c = getchar())!='\n'); printf("ctrl-c count = %d\n", ctrl_c_count);
(void) signal(SIGINT, old_handler);
for (;;);}
void ctrl_c(int signum){ (void) signal(SIGINT, ctrl_c); ++ctrl_c_count;}
![Page 16: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/16.jpg)
output
> ./a.out
^C^C^C
ctrl-c count = 3
^C
>
![Page 17: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/17.jpg)
sigsaction( ) system call
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
used to associate an action with a signal
signum is the number of the signal to handle
May be a symbolic name
May not be SIGKILL or SIGSTOP
act is a structure that holds the pointer to the name of the handler to associate with the signal
oldact holds the pointer to the routine that was the signal's previous handler
One important difference between sigaction and signal
The signal handling routine stays installed even after a signal has been caught
So you don't have to reset the signal handler in the signal handling routine
![Page 18: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/18.jpg)
struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags;} sa_handler - the name of the handler sa_sigaction - do not use for now sa_mask - gives a mask of signals which should be blocked during execution of
the signal handler flags - modify the behavior of the signal handling process
Here is a list of flags on brunel. See man pages for details.– SA_ONSTACK – SA_RESETHAND– SA_NODEFER – SA_RESTART – SA_SIGINFO – SA_NOCLDWAIT – SA_NOCLDSTOP
![Page 19: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/19.jpg)
sigaction_ex.c #include <stdio.h>
#include <stdlib.h>#include <signal.h>#include <unistd.h>
int ctrl_c_count = 0;void ctrl_c(int);
main(){ int c, i; struct sigaction new_action; struct sigaction old_action;
new_action.sa_handler = ctrl_c; new_action.sa_flags = 0;
sigaction( SIGINT, &new_action, &old_action );
for ( i = 0; i < 3; i++ ) { while ((c = getchar())!='\n'); printf("ctrl-c count = %d\n", ctrl_c_count); }
sigaction( SIGINT, &old_action, NULL );
for (;;);}
void ctrl_c(int signum){ ++ctrl_c_count;}
![Page 20: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/20.jpg)
output
> ./a.out
^C^C
ctrl-c count = 2
^C^C^C^C
ctrl-c count = 6
^C^C^C^C
ctrl-c count = 10
^C
>
![Page 21: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/21.jpg)
sigprocmask( ) system call Each process has a signal mask which is a set of signals that are currently
blocked from delivery If a blocked signal is sent to a process anyway
It is added to a set of pending signals for the process It will be delivered when the block is removed
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
changes the list of currently blocked signals how indicates how the list of signals in set should be treated
SIG_BLOCK The set of blocked signals is the union of the current set and set
SIG_UNBLOCK The signals in set are removed from the current set of blocked signals
SIG_SETMASK The set of blocked signals is set to set
oldset contains the previous value of the signal mask
![Page 22: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/22.jpg)
Example: sigprocmask_ex.c
In this example, I will use SIGUSR1 and SIGUSR2.
The definition of these in signal.h is:
Name Value Default Event SIGUSR1 16 Exit User Signal 1 SIGUSR2 17 Exit User Signal 2
![Page 23: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/23.jpg)
#include <stdio.h>#include <signal.h>#include <unistd.h>
sigset_t new_signals;
int main(){ void signal_catcher( int ); // forward declaration of handler struct sigaction new_action;
sigemptyset( &new_signals ); // Empties the set of blocked signals sigaddset( &new_signals, SIGUSR1 ); // Adds SIGUSR1 to the set of // blocked signals
sigprocmask( SIG_BLOCK, &new_signals, NULL ); // Unions the set of process // blocked signals with new_signals
new_action.sa_handler = signal_catcher; new_action.sa_flags = 0;
/* Associate the handler with SIGUSR2 */ sigaction( SIGUSR2, &new_action, NULL );
printf( "Waiting for signal\n" ); pause( ); // Sleep until a signal is received printf( "Done\n" ); return 0;}
![Page 24: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/24.jpg)
void signal_catcher( int n ){ printf( "Received signal %i will release SIGUSR1\n", n ); sigprocmask( SIG_UNBLOCK, &new_signals, NULL ); printf( "SIGUSR1 released!\n" );}
![Page 25: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/25.jpg)
Output> ./a.out &
[1] 21551
> Waiting for signal
kill -USR1 21551
> ps
PID TTY TIME CMD
21339 pts/17 0:00 tcsh
21558 pts/17 0:00 ps
21329 pts/17 0:00 csh
21551 pts/17 0:00 a.out
> kill -USR2 21551
Received signal 17 will release SIGUSR1
> ps
PID TTY TIME CMD
21339 pts/17 0:00 tcsh
21329 pts/17 0:00 csh
21559 pts/17 0:00 ps
[1] + User signal 1 ./a.out
Pending signal SIGUSR1 can now
terminate the process
![Page 26: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/26.jpg)
sigsuspend( ) system call
int sigsuspend(const sigset_t *mask);
Is used to suspend a process
It replaces the current signal mask with mask
The process is suspended until a signal is delivered whose action is to
Execute a signal-catching function
Or terminate the process
If the action is to terminate the process, sigsuspend() does not return.
If the action is to execute a signal catching function, sigsuspend() returns after the signal catching function returns. On return, the signal mask is restored to the set that existed before the call to sigsuspend().
![Page 27: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/27.jpg)
sigsuspend_ex.c
/* This program demonstrates using sigsuspend
To use: 1. a.out & 2. kill -USR1 %1 3. kill -INT %1 4. Then immediately issue a jobs command
*/
![Page 28: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/28.jpg)
#include <stdio.h>#include <signal.h>#include <unistd.h>
int main(){ void signal_catcher( int ); // forward declaration of handler struct sigaction new_action; sigset_t no_sigs, blocked_sigs, all_sigs;
sigfillset( &all_sigs ); // Turn all bits on sigemptyset( &no_sigs ); // Turn all bits off to mean no signals blocked
sigemptyset( &blocked_sigs ); // Initialize
new_action.sa_handler = signal_catcher; new_action.sa_mask = all_sigs; new_action.sa_flags = 0;
/* Associate the handler with SIGUSR1 */ sigaction( SIGUSR1, &new_action, NULL );
sigaddset( &blocked_sigs, SIGUSR1 ); sigprocmask( SIG_SETMASK, &blocked_sigs, NULL ); while( 1 ) { printf( "Waiting for SIGUSR1 signal\n" ); sigsuspend( &no_sigs ); }
printf( "Done\n" ); return 0;}
![Page 29: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/29.jpg)
void signal_catcher( int n ){ printf( "Beginning important stuff...\n" ); sleep( 10 ); printf( "Ending important stuff\n" );}
![Page 30: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/30.jpg)
Output
> ./a.out &
[1] 21674
> Waiting for SIGUSR1 signal
kill -USR1 21674
Beginning important stuff...
Ending important stuff
Waiting for SIGUSR1 signal
kill -INT 21674
> ps
PID TTY TIME CMD
21339 pts/17 0:00 tcsh
21683 pts/17 0:00 ps
21329 pts/17 0:00 csh
[1] + Interrupt ./a.out
![Page 31: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/31.jpg)
Example: alarm_ex.c/* This program demonstrates the alarm( ) system call */
#include <stdio.h>#include <signal.h>
int alarmFlag = 0; /* alarm flag */void alarmHandler(); /* Forward declaration of alarm handler */
main(){ signal(SIGALRM, alarmHandler); /* Install signal handler */ alarm(3); /* Schedule an alarm signal in 3 seconds */ printf("Looping....\n"); while(!alarmFlag) /* Loop until flag set */ { pause(); /* Wait for signal */ } printf("Loop ends due to alarm signal\n");}
void alarmHandler(){ printf("An alarm clock signal was received\n"); alarmFlag = 1;}
![Page 32: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/32.jpg)
output
> ./a.out
Looping....
An alarm clock signal was received
Loop ends due to alarm signal
>
![Page 33: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/33.jpg)
Example: sigchld_ex.c
/* This program allows a user to limit the amount of time that a command takes to execute. The first parameter to sigchld.out is the maximum # of seconds that is allowed for execution, and the remaining parameters are the command itself.
STEPS: 1. Parent process installs a SIGCHLD handler 2. Parent forks a child process to execute the command 3. Parent sleeps for specified number of seconds. When it wakes up, it sends the child process a SIGINT to kill it 4. If child terminates before its parent wakes up, the parent's SIGCHLD handler is executed, causing the parent to terminate immediately.
To use: a.out <num of secs> <command>
*/
![Page 34: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/34.jpg)
#include <stdio.h>#include <stdlib.h>#include <signal.h>
int delay;void childHandler();
main(int argc, char* argv[]){ int pid; signal(SIGCHLD, childHandler); /* Install death-of-child handler */
pid = fork(); /* Duplicate */ if (pid == 0) /* Child */ { execvp(argv[2], &argv[2]); /* execute command */ perror("sigchld"); /* Should never execute */ } else /* parent */ { sscanf(argv[1], "%i", &delay); /* Read delay from command line */ printf("delay is: %i\n", delay); sleep(delay); /* Sleep for the specified number of seconds */ printf("Child %i exceeded limit and is being killed\n", pid); kill(pid, SIGINT); /* Kill the child */ }}
![Page 35: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/35.jpg)
void childHandler(){ int childPid, childStatus; childPid = wait(&childStatus); /* Accept child's termination code */ printf("Child %i terminated within %i seconds\n", childPid, delay); exit (0);}
![Page 36: Signals and Signal Handling. Signals A predefined message sent between two processes or from the kernel to a process, or by a user to a process A software](https://reader036.vdocuments.site/reader036/viewer/2022062423/5697bf841a28abf838c870ab/html5/thumbnails/36.jpg)
output
> ./a.out 2 ls
delay is: 2
a.out sigaction_ex.c signal_ex.c sigpending_ex.c sigsuspend_ex.c
alarm_ex.c sigchld_ex.c signal_ex2.c sigprocmask_ex.c
Child 21804 terminated within 2 seconds
> ./a.out 2 sleep 4
delay is: 2
Child 21806 exceeded limit and is being killed
>