Documente Academic
Documente Profesional
Documente Cultură
Last Week:
! How to program UNIX processes (Chapters 7-9)
! fork() and exec()
Unix System Programming
This Week:
Signals ! UNIX inter-process communication mechanism:
signals, pipes and FIFOs.
! How to program with UNIX signals (Chapter 10)
! Non-local jumps (Chapter 7)
! Focus on the sigaction() function
#include <signal.h>
! After receiving a signal a process can:
1. Ignore/Discard/Block out the signal (not possible with void (*signal( int signo, void (*func)(int) ))(int);
SIGKILL or SIGSTOP)
2. Catch the signal; execute a signal handler function, and typedef void Sigfunc( int ); /* Plauger 1992 definition */
then possibly resume execution or terminate Sigfunc *signal( int signo, Sigfunc *handler );
3. Carry out the default action for that signal
! Signal returns a pointer to a function that returns an int (i.e. it
! The choice is called the process’ signal disposition returns a pointer to Sigfunc)
! Specify a signal handler function to deal with a signal type.
! Returns previous signal disposition if OK, SIG_ERR on error.
void (*signal( int signo, void (*handler)(int)))(int); /* do usual things until SIGINT */
return 0;
! signal returns a pointer to the previous signal handler }
To keep catching
the signal with this
Reset Problem function, must call
the signal system
Re-installation may be too slow!
call again.
:
void ouch( int sig ) ! There is a (very) small time period in foo() when
{ a new SIGINT signal will cause the default action
printf( "OUCH! - I got signal %d\n", sig );
(void) signal( SIGINT, ouch );
to be carried out -- process termination.
} Problem: from the time
int main() that the interrupt function ! With signal() there is no answer to this
starts to just before the
{
signal handler is re- problem.
(void) signal( SIGINT, ouch ); established » POSIX signal functions solve it (and some other later
while(1) the signal will not be UNIXs)
{ handled.
printf( "Hello World!\n");
sleep(1);
}
If another SIGINT signal is
} received during this time,
default behavior will be done,
i.e., program will terminate.
Maria Hybinette, UGA 21 Maria Hybinette, UGA 22
:
! Ignore a signal int main()
{
! Clean up and terminate signal( SIGINT, SIG_IGN );
signal( SIGQUIT, SIG_IGN );
! Dynamic reconfiguration :
/* do work without interruptions */
! Report status }
! Turn debugging on/off
! Cannot ignore/handle SIGKILL or SIGSTOP
! Restore a previous handler
! Should check for SIG_ERR
to be cancelled.
void sig_alrm( int signo )
/* do nothing, just handle signal */
{
return;
}
! The signal set stores collections of signal int sigemptyset( sigset_t *set );
int sigfillset( sigset_t *set );
types.
int sigaddset( sigset_t *set, int signo );
! Sets are used by signal functions to define int sigdelset( sigset_t *set, int signo );
which signal types are to be processed. int sigismember( const sigset_t *set, int signo );
! POSIX contains several functions for creating, ! sigemptyset - initializes signal set pointed by set
changing and examining signal sets. so that all signals are excluded
! sigfillset - all signals are included
! sigaddset - add a single signal (signo) to set
! sigdelset - remove signo from set
Maria Hybinette, UGA 51 Maria Hybinette, UGA 52
/* block SIGINT; save old mask */ ! Supercedes (more powerful than) signal()
sigprocmask( SIG_BLOCK, &newmask, &oldmask ); » sigaction() can be used to code a non-resetting signal()
/* critical region of code */ ! signo is the signal you want to perform an action on
! act is the action
/* reset mask which unblocks SIGINT */
sigprocmask( SIG_SETMASK, &oldmask, NULL ); ! oact is the old action (can be set to NULL, if uninteresting)
: ! Cannot handle SIGSTOP and SIGKILL
Signal Raising
struct sigaction Signal Raising
{
void (*) (int) sa_handler
#include <signal.h> {cinnamon:ingrid:8} sigact
sigset_t sa_mask
#include <stdio.h> Hello World!
int sa_flags
void ouch( int signo )
{ printf( “OUCH! signo = %d\n, signo ); }
Hello World!
}
! This function will continually capture the
Hello World! Ctrl-c (SIGINT) signal.
int main() Hello World!
{
struct sigaction act; OUCH! signo = 2
No World!
Hello flags are needed here. ! Default behavior is not restored after signal
act.sa_handler = ouch;
Possible
Hello World! flags
Helloinclude:
World!
is caught.
sigemptyset( &(act.sa_mask) ); SA_NOCLDSTOP
Hello World!
SA_RESETHAND
act.sa_flags = 0; SetTerminated
the signal handler to
SA_RESTART ! To terminate the program, must type ctrl-\,
function ouch
be theSA_NODEFER
sigaction( SIGINT, &act, NULL ); the SIGQUIT signal (or sent a TERM signal via
kill)
while( 1 )
{
We can manipulate
printf("Hello World!\n"); This call sets the signal
sets of signals..
sleep(1); handler for the SIGINT
}
(Ctrl-c) signal
}
Maria Hybinette, UGA 59 Maria Hybinette, UGA 60
sigexPOS.c
! Other than SIGKILL and SIGSTOP, signals ! The third parameter to sigaction, oact, can
can be ignored: be used:
act.sa_handler = SIG_IGN;
sigaction( SIGTERM, &act, NULL );
Then the ^C key will be ignored
Sigfunc *signal( int signo, Sigfunc *func ) ! sigpending() examine blocked signals
{
struct sigaction act, oact;
! sigsetjmp()
act.sa_handler = func; siglongjmp() jump functions for use
sigemptyset( &act.sa_mask ); in signal handlers which
act.sa_flags = 0; handle masks correctly
act.sa_flags |= SA_INTERRUPT;
if( signo != SIGALRM )
! sigsuspend() atomically reset mask
act.sa_flags |= SA_RESTART;
and sleep
/* any system call interrupted by a signal
* other than alarm is restarted */
if( sigaction( signo, &act, &oact ) < 0 )
return(SIG_ERR);
return( oact.sa_handler );
}
Maria Hybinette, UGA 65 Maria Hybinette, UGA 66
[sig]longjmp & [sig]setjmp Example
#include <stdio.h> …
#include <signal.h> while(1)
NOTES (longjmp, sigjmp) #include <setjmp.h> {
POSIX does not specify whether longjmp will restore sleep(5);
sigjmp_buf buf; printf(“ waiting...\n");
the signal context. If you want to save and restore }
signal masks, use siglongjmp. void handler(int sig) }
{
siglongjmp(buf, 1); > a.out
NOTES (setjmp, sigjmp) } starting
POSIX does not specify whether setjmp will save the waiting...
signal context. (In SYSV it will not. In BSD4.3 it will, main() waiting...
Control-c
and there is a function _setjmp that will not.) If you { restarting
signal(SIGINT, handler); waiting...
want to save signal masks, use sigsetjmp.
waiting...
if( sigsetjmp(buf, 1) == 0 ) waiting...
printf("starting\n"); restarting Control-c
else waiting...
restarting Control-c
printf("restarting\n"); waiting...
Maria Hybinette, UGA 67 … Hybinette, UGA
Maria waiting... 68
! When a system call (e.g. read()) is ! Slow system functions carry out I/O on things
interrupted by a signal, a signal handler is that can possibly block the caller forever:
called, returns, and then what? » pipes, terminal drivers, networks
» some IPC functions
! On many UNIXs, slow system function calls » pause(), some uses of ioctl()
do not resume. Instead they return an error
and errno is assigned EINTR. ! Can use signals on slow system functions to
» true of Linux, but can be altered with (Linux- code up timeouts (e.g. did earlier )
specific) siginterrupt()
! Most system functions are non-slow, ! If a system function is called inside a signal
including ones that do disk I/O handler then it may interact with an interrupted
» e.g. read() of a disk file call to the same function in the main code.
» read() is sometimes a slow function, sometimes » e.g. malloc()
not
jmp_buf env; P1
P1() env P2
{
P2(); P3(); At setjmp
}
P1
P2()
{ if( setjmp( env ) env X P2
/* long jump to here */
} P2 returns
P3() P1
{
longjmp( env, 1 ); env X P3
}
At longjmp