signals and signal handling. signals a predefined message sent between two processes or from the...

36
Signals and Signal Handling

Upload: leon-logan

Post on 17-Jan-2016

217 views

Category:

Documents


0 download

TRANSCRIPT

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

#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

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

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

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

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

#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

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

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

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

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

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

#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

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

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

>