0% found this document useful (0 votes)
41 views

Unix Signals

Uploaded by

Rahul Sreedharan
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
41 views

Unix Signals

Uploaded by

Rahul Sreedharan
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 42

UNIX Signals

Reminder: Kernel Mode


• When the CPU is in kernel mode, it is
assumed to be executing trusted software,
and thus it can execute any instructions and
reference any memory addresses.
• The kernel is the core of the operating system
and it has complete control over everything
that occurs in the system.
• The kernel is trusted software, all other
programs are considered untrusted software.
• A system call is a request to the kernel in a
Unix-like operating system by an active
process for a service performed by the kernel.
2
Some Definitions
• A process is an executing instance of a
program. An active process is a process that is
currently advancing in the CPU (while other
processes are waiting in memory for their turns
to use the CPU).
• The execution of a process can be interrupted
by an interrupt.
• An interrupt is a notification to the operating
system that an event has occurred, which
results in changes in the sequence of
instructions that is executed by the CPU.

3
Types of Interrupts
• Hardware interrupts (also called
external/asynchronous interrupts), are ones in
which the notification originates from a hardware
device such as a keyboard, mouse or system
clock.
• Software interrupts include exceptions and traps
• Exceptions: trigerred by an action of the process
without its knowledge (division by zero, access to paged
memory, etc.)
• Traps: trigerred by the process using system calls
• Usually, no interrupt should be ignored by the OS.

4
Interrupts:
The basic mechanism
1. The CPU receives the interrupt,
2. Control is transferred to the OS,
3. Current state is saved,
4. The request is serviced,
5. Previous state is restored,
6. Control is returned.

5
Signals
• Signals are notifications sent to a process in order to notify
it of various "important" events.
• Signals cause the process to stop whatever it is doing at
the moment, and force the process to handle them
immediately.
• The process may configure how it handles a signal.
• (Except for some signals that it cannot configure)
• Signals are different from interrupts:
• Signals are generated by the OS,
and received and handled by a process.
• Interrupts are generated by the hardware,
and received and handled by the OS.
• Signals and interrupts are both asynchronous
• Signals in unix have names and numbers.
• Use ‘man kill’ to see the types of signals
Definition of Signal
Signal: A notification of an event
Event gains attention of the OS
OS stops the application process immediately, sending it a signal
Signal handler executes to completion
Application process resumes where it left off

Process
movl
void handler(int iSig)
pushl
{
call f …
addl }
movl
.
.
.
signal 7
Triggers for Signals
Some examples for signal triggers:
– Asynchronous input from the user such as ^C
(SIGINT), or typing ‘kill pid’ at the shell
– The system or another process, for instance if an
alarm set by the process has timed out
(SIGALRM)
– An exception in hardware caused by the process,
such as Illegal memory access (SIGSEGV)
• The exception causes a hardware interrupt,
• The hardware interrupt is received by the OS
• The signal is generated by the OS and 'sent' to the process
– A debugger wishing to suspend or resume the
process
Sources
* Hardware
for Generating Signals
- A process attempts to access addresses outside its own address
space.
- Divides by zero.
* Kernel
- Notifying the process that an I/O device for which it has been
waiting is available.
* Other Processes
- A child process notifying its parent process that it has
terminated.
* User
- Pressing keyboard sequences that generate a quit, interrupt or
stop signal.
Three Courses of Action
Process that receives a signal can take one of three action:
* Perform the system-specified default for the signal
- notify the parent process that it is terminating;
- generate a core file;
(a file containing the current memory image of the process)
- terminate.
* Ignore the signal
A process can do ignoring with all signal but two special signals:
SIGSTOP and SIGKILL.
* Catch the Signal
When a process catches a signal, except SIGSTOP and SIGKILL, it
invokes a special signal handing routine.
Sending Signals Using the Keyboard
The most common way of sending signals to
processes is using the keyboard:
• Ctrl-C: Causes the system to send an INT
signal (SIGINT) to the running process.
• Ctrl-Z: causes the system to send a TSTP
signal (SIGTSTP) to the running process.
• Ctrl-\:causes the system to send a ABRT
signal (SIGABRT) to the running process.
Sending Signals from
the Command Line
•The kill command sends a signal to a process.

kill [options] pid


-l lists all the signals you can send
-signal defines the signal to send
•the default is to send a TERM signal to the process.

•The fg command resumes


execution of a process (that was
suspended with Ctrl-Z), by sending it a
CONT signal.
Handling Signals
• The kernel handles signals in the context
of the process that receives them, so
a process must run to handle signals.
• There are three types of handling for
signals:
• The process exits. (default for some signals)
• The process ignores. (default for some
other signals)
• The process executes a signal handler:
oldfun = signal(signum,newfun);
Signal Handlers – Example
(Note: “signal” is deprecated!)
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void catch_int(int sig_num) {


signal(SIGINT, catch_int); //install again!
printf("Don't do that\n");
fflush(stdout);
}

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


signal(SIGINT, catch_int);
for ( ;; )
pause();//wait until receives a signal.
}
Handling Signals (cont.)
• There are some signals that the process cannot
catch.
• For example: KILL and STOP.
• If you install no signal handlers of your own, the
runtime environment sets up a set of default signal
handlers.
• For example:
• The default signal handler for TERM calls
exit().
• The default handler for ABRT is to dump the
process's memory image into a file, and then
exit.
Pre-defined Signal Handlers
• There are two pre-defined signal
handler functions that we can use:,
instead of writing our own.
• SIG_IGN: Causes the process to ignore
the specified signal.
• signal(SIGINT, SIG_IGN);
• SIG_DFL: Causes the system to set the
default signal handler for the given signal.
• signal(SIGTSTP, SIG_DFL);
Intermediate Summary
• Each signal may have a signal handler,
which is a function that gets called when the
process receives that signal.
• If a signal is sent to the process, the next
time the process runs, the operating system
causes the process to run the signal
handler, no matter what it was doing before.
• When that signal handler function returns,
the process continues execution from
wherever it happened to be before the signal
was received.
POSIX-Defined Signals (1)
* SIGALRM: Alarm timer time-out. Generated by alarm( ) API.
* SIGABRT: Abort process execution. Generated by abort( ) API.
* SIGFPE: Illegal mathematical operation.
* SIGHUP: Controlling terminal hang-up.
* SIGILL: Execution of an illegal machine instruction.
* SIGINT: Process interruption. Can be generated by <Delete> or
<ctrl_C> keys.
* SIGKILL: Sure kill a process. Can be generated by
“kill -9 <process_id>“ command.
* SIGPIPE: Illegal write to a pipe.
* SIGQUIT: Process quit. Generated by <crtl_\> keys.
* SIGSEGV: Segmentation fault. generated by de-referencing a NULL
pointer.
POSIX-Defined Signals (2)
* SIGTERM: process termination. Can be generated by
“kill <process_id>” command.
* SIGUSR1: Reserved to be defined by user.
* SIGUSR2: Reserved to be defined by user.
* SIGCHLD: Sent to a parent process when its child process has
terminated.
* SIGCONT: Resume execution of a stopped process.
* SIGSTOP: Stop a process execution.
* SIGTTIN: Stop a background process when it tries to read from from
its controlling terminal.
* SIGTSTP: Stop a process execution by the control_Z keys.
* SIGTTOUT: Stop a background process when it tries to write to its
controlling terminal.
From Advanced Programming in the UNIX® Environment, Third Edition, by W. Richard Stevens and Stephen A. Rago (ISBN-13: 978-0-321-63773-4). Copyright © 2013 by Pearson Education, Inc. All rights reserved.
From Advanced Programming in the UNIX® Environment, Third Edition, by W. Richard Stevens and Stephen A. Rago (ISBN-13: 978-0-321-63773-4). Copyright © 2013 by Pearson Education, Inc. All rights reserved.
Signaling Processes
* Signal
A signal is a notification to a process that an event has
occurred. Signals are sometimes called “software
interrupts”.
* Features of Signal
- Signal usually occur asynchronously.
- The process does not know ahead of time exactly when a
signal will occur.
- Signal can be sent by one process to another process (or to
itself) or by the kernel to a process.
Avoiding Signal Races –
Masking Signals
• Because signals are handled asynchronously,
race conditions can occur:
• A signal may be recieved and handle in the middle of
an operation that should not be inerrupted;
• A second signal may occur before the current signal
handler finished.
• The second signal may be of a different type or of the same
type as the first one.
• Therefore we need to block signals from being processed
when they are harmful.
• The blocked signal will be processed after the block is removed.
• Some signals cannot be blocked.
Sigprocmask
Allows to specify a set of signals to block, and/or get the list of
signals that were previously blocked.
int sigprocmask(int how, const sigset_t *set,
sigset_t *oldset)
1.int how: sigset_t set;
• Add (SIG_BLOCK)
sigemptyset(&set);
• Delete (SIG_UNBLOCK) sigaddset(&set, SIGINT);
sigaddset(&set, SIGTERM);
• Set (SIG_SETMASK). sigprocmask(SIG_SETMASK, &set, NULL);
//blocked signals: SIGINT and SIGTERM
2.const sigset_t *set: sigemptyset(&set);
• The set of signals. sigaddset(&set, SIGINT);
sigaddset(&set, SIGALRM);
3.sigset_t *oldse: sigprocmask(SIG_BLOCK, &set, NULL);
//blocked signals: SIGINT, SIGTERM, SIGALRM
1. If not NULL, the previous
sigemptyset(&set);
mask will be returned. sigaddset(&set, SIGTERM);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &set, NULL);
//blocked signals: SIGINT and SIGALRM
Handling Signals
• So far we saw two system calls:
• signal
• Installs a signal for a single use,
• Must reinstall each time we get a signal!
• Deprecated!
• sigprocmask
• Defines which signals to block,
• Must be called in each signal handler to block and
release signals.
Sigaction
int sigaction(int sig,
struct sigaction *new_act,
struct sigaction *old_act);
• Allows the calling process to examine
and/or specify the action to be
associated with a specific signal.
• action = signal handler+signal mask+flags
Sigaction cont.

• The signal mask is calculated and installed


only for the duration of the signal handler.
• By default, the signal “sig” is also blocked
when the signal occurs.
• Once an action is installed for a specific
signal using sigaction, it remains installed
until another action is explicitly requested.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void termination_handler(int signum) {
exit(7);
}

int main (void) {


struct sigaction new_action,old_action;
new_action.sa_handler =
termination_handler;
sigemptyset(&new_action.sa_mask);
sigaddset(&new_action.sa_mask, SIGTERM);
new_action.sa_flags = 0;
sigaction(SIGINT, NULL, &old_action);
if (old_action.sa_handler != SIG_IGN) {
sigaction(SIGINT,&new_action,NULL);
}
sleep(10);
return 0;
}
sigprocmask API - Signal Mask (1)
* Function
A process can query or set its signal mask via the
sigprocmask API.
* Include: <signal.h>
* Summary: int sigprocmask ( int cmd,
cost sigset_t *new_mask, sigset_t *old_mask);
* Return:
Success: 0
Failure: -1
Sets errno: Yes
Arguments of sigprocmask API
- Signal Mask (2)
* new_mask: defines a set of signals to be set or reset in a calling process
signal mask.
new_mask = NULL, current process signal mask unaltered.
* cmd: specifies how the new_mask value is to be used:
- SIG_SETMASK: Overrides the calling process signal mask with the
value specified in the new_mask argument.
- SIG_BLOCK: Adds the signals specified in the new_mask argument to
the calling process signal mask.
- SIG_UNBLOCK: Removes the signals specified in the new_mask
argument from the calling process signal mask
* old_mask: Address of a sigset_t variable that will be assigned the
calling processing’s original signal mask.
old_mask = NULL, no previous signal mask will be return.
sigsetops APIs - Signal Mask (3)
* int sigemptyset (sigset_t* sigmask);
Clears all signal flags in the sigmask argument.
* int sigaddset (sigset_t* sigmask, const int signal_num);
Sets the flag corresponding to the signal_num signal in the sigmask
argument.
* int sigdelset (sigset_t* sigmask, const int signal_num);
Clears the flag corresponding to the signal_num signal in the sigmask
argument.
* int sigfillset(sigset_t* sigmask);
Sets all the signal flags in the sigmask argument.
* int sigismember(const sigset_t* sigmask,const int signal_num);
Returns 1 if the flag corresponding to the signal_num signal in the
sigmask argument is set; zero: not set; -1: the call fails.
sigprocmask Example -Signal Mask
(4) signal is present in a process
/* The example checks whether the SIGINT
signal mask and adds it to the mask if it is not there.
It clears the SIGSEGV signal from the process signal mask. */
int main( ){
sigset_t sigmask;
sigemptyset(&sigmask); /*initialize set */
if(sigprocmask(0,0,&sigmask)==-1)/*get current signal mask*/
{ perro(“sigprocmask”); exit(1); }
else sigaddset(&sigmask, SIGINT); /* set SIGINT flag*/
sigdelset(&sigmask, SIGSEGV); /* clear SIGSEGV flag */
if (sigprocmask(SIG_SETMASK,&sigmask,0) == -1)
perro(“sigprocmask”); /* set a new signal mask */
}
sigpending API- Signal Mask (5)
* Function
The sigpending API can find out whether one or more signals are
pending for a process and set up special signal handing methods
for those signals before the process calls the sigprocmask API to
unblock them.
* Include: <signal.h>
* Summary: int sigpending (sigset_t* sigmask);
* Return: Success: 0; Failure: -1; Sets errno: Yes
* Argument
sigmask argument, to the sigpending API, is the address of a
sigset_t-type variable and is assigned the set of signals pending
for the calling process by the API.
sigpending Example - Signal Mask (6)
/* The example reports to the console whether the SIGTERM signal
is pending for the process. */
int main ( ) {
sigset_t sigmask;
sigemptyset(&sigmask); /* initialize set */
if (sigpending(&sigmask) == -1) /* Any signal is pending */
perro(“sigpending”);
else
cout<<”SIGTERM signal is:” <<
(sigismember (&sigmask,SIGTERM) ? “Set” : “No Set”);
/* whether SIGTERM signal in the sigmask argument is set? */
sigaction API - sigaction (1)
* Function
.The sigaction API setups a signal handling method for each
signal it wants to deal with and passes back the previous
signal handling method for a given signal. The sigaction API
blocks the signal it is catching allowing a process to specify
additional signals to be blocked when the API is handling a
signal.
* Include: <signal.h>
* Summary: int sigaction ( int signal_num,
struct sigaction* action, struct sigaction* old_action);
* Return: Success: 0; Failure: -1; Sets errno: Yes
struct sigaction - sigaction (2)
* struct sigaction
{
void (*sa_handler) (int);
sigset_t sa_mask;
int sa_flag;
}
* sa_handler is the function point of a user-defined signal handler
function, SIG_IGN (ignores a signal), or SIG_DFL (accepts the
default action of a signal).
* sa_mask specifies additional signals that a process wishes to block
when it is handling the signal_num signal.
* sa_flag specifies special handling for certain signals.
sa_flag value - sigaction (3)
0: when the signal_num is SIGCHLD, the kernel will send the
SIGCHLD signal to the calling process whenever its child
process is either terminated or stopped.
SA_NOCLDSTOP: when the signal_num is SIGCHLD, the kernel
will generate the SIGCHLD signal to the calling process
whenever its child process is either terminated, but not when the
child process has been stopped.
SA_RESETHAND: If signal_num is caught, the sa_handler is set to
SIG_DFL before the signal handler function is called, and
signal_num will not be added to the process signal mask
SA_RESTART: If a signal is caught while a process is executing a
system call, the kernel will restart the system call after the signal
handler returns. If this flag is not set in the sa_flag, after the
signal handler returns, the system call will be aborted with a
return value of -1 and will set errno to EINTR (aborted due to a
signal interruption).
Arguments of sigaction - sigaction (4)
* signal_num
The signal_num argument designates which signal handling
action is defined in the action argument.
* old_action
The previous signal handling method for signal_num will be
returned via the old_action argument if it is not a NULL pointer.
* action
action argument sets up a signal handling method for the
signal_num argument.
If the action argument is a NULL pointer, the calling process’s
existing signal handling method for signal_num will be
unchanged.
! Example: sigaction.C
kill API - kill and sigaction(1)
* Function
- A process can send a signal to a related process via the kill API.
- This is a simple means of interprocess communication or
control.
- The sender and recipient processes must be related such that
either the sender process real or effective user ID matches that of
the recipient process, or the sender process has superuser
privileges.
* Include: <signal.h>
* Summary: int kill ( pid_t pid, int signal_num);
* Return: Success: 0; Failure: -1; Sets errno: Yes
Arguments of kill - kill and sigaction (2)
* int signal_num: the integer value of a signal to be sent to one
or more processes designated by pid.
* pid_t pid value
- positive value: pid is process ID. Sends signal_num to that
process.
- 0: sends signal_num to all process whose group ID is
the same as the calling process.
- -1: Sends signal_num to all processes whose real user ID
is the same as the effective user ID of the calling
process.

Example: killpipe.c
alarm API - alarm
* Function
The alarm API requests the kernel to send the SIGALRM
signal after a certain number of real clock seconds.
* Include: <signal.h>
* Summary: unsigned int kill ( unsigned int time_interval);
* Return:
Success: the number of CPU seconds left in the process
timer; Failure: -1; Sets errno: Yes
* Argument
time_interval: the number of CPU seconds elapsed time,
after which the kernel will send the SIGALRM signal to the
calling process.
Signals: Summary
• Signals are notifications sent to a process
• The OS causes the process to handle a
signal immediately the next time it runs.
• There are default signal handlers for
processes.
• These handlers can be changed using
signal or sigaction.
• To avoid race conditions, one usually needs
to block signals some of the time using
sigprocmask and/or sigaction.

You might also like