[unix programming] signal and signal processing
Post on 05-Jan-2016
142 Views
Preview:
DESCRIPTION
TRANSCRIPT
[Unix Programming][Unix Programming]Signal and Signal ProcessingSignal and Signal Processing
Young-Ju, HanYoung-Ju, Han
Email: yjhan@imtl.skku.ac.krEmail: yjhan@imtl.skku.ac.kr
2007 UNIX Programming2007 UNIX Programming
ContentsContents
Introduction signal names normal and abnormal termination
signal handling signal sets setting the signal action : signal & sigaction
Signal blocking Sending signals
to other processes : kill to yourself : raise and alarm pause system call
2007 UNIX Programming2007 UNIX Programming
IntroductionIntroduction
Signals A simple method for transmitting software interrupts to UNIX processes Asynchronous events has a name
begin with the three characters SIG defined by positive integer constants
<signal.h> 0 : special usage (normal error checking)
It is often used to determine if a specific process still exists.
3 things with signals signal handling signal blocking signal sending
Terminology generate : when event causes the signal occur delivered : when action for a signal is taken pending : during the time between generation and delivery option of block
if generated and action is default or catch then pending until unblocks or changes to ignore
2007 UNIX Programming2007 UNIX Programming
IntroductionIntroduction
Signal name
/usr/include/sys/iso/signal_iso.h default action
SIGABRT 6 abnormal termination (calling abort()) terminate w / core
SIGALRM 14 Alarm clock (time out) terminate
SIGBUS bus error (hardware fault) terminate w / core
SIGCHLD 18 child process terminated or stopped ignore
SIGCONT continue executing if stopped (job control) continue / ignore
SIGFPE arithmetic exception (floating-point exception) terminate w / core
SIGHUP 1 hang up terminate
SIGILL 4 illegal hardware instruction terminate w / core
SIGINT 2 terminal interrupt character terminate
SIGKILL 9 Kill, termination terminate
SIGPIPE 13 write on pipe or socket when recipient has terminated terminate
SIGPOLL pollable event terminate
SIGPROF profiling time expired terminate
signal name
2007 UNIX Programming2007 UNIX Programming
IntroductionIntroduction
Signal name /usr/include/sys/iso/signal_iso.h default action
SIGQUIT 3 terminal quit character terminate w / core
SIGSEGV invalid memory reference terminate w / core
SIGSTOP 23 Stop executing stop process
SIGSYS invalid system call terminate w / core
SIGTERM Software termination signal terminate
SIGTRAP 5 Trace trap, abnormal termination terminate w / core
SIGTSTP terminal stop character stop process
SIGTTIN background process attempting read from control tty stop process
SIGTTOU background process attempting write to control tty stop process
SIGURG urgent condition (socket) ignore
SIGUSR1 user-defined signal terminate
SIGVTALRM virtual timer alarm terminate
SIGXCPU CPU time limit exceeded terminate w / core
SIGXFSZ file size limit exceeded terminate w / core
2007 UNIX Programming2007 UNIX Programming
IntroductionIntroduction
abnormal termination SIGABRT, SIGBUS, SIGSEGV, SIGQUIT, SIGILL,
SIGTRAP, SIGSYS, SIGXCPU, SIGXFSZ, SIGFPEcore dump file
memory dump of process values of all program variables, h/w register and control
information from the kernel when it terminate
WCOREDUMP(status)
abort();SIGABRT signalcore dumpa process can send a signal to itself
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
disposition of the signal (action) We can tell the kernel to do when a signal occurs ignore the signal
When delivered to process, it is discardednever be ignored: SIGKILL, SIGSTOP
Let the default action applyterminate process (abnormal terminate)ignore (SIGCHLD )stop (SIGSTOP,SIGSTP)
catch the signaltake a specified user-defined actionto perform clean-up operationNever be catched: SIGKILL, SIGSTOP
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
signo : signal name sa_handler
SIG_IGN , SIG_DFL , user_defined signal handler
#include <signal.h>
void (*signal(int signo, void (*sa_handler)(int)))(int);Returns : previous disposition of signal (see following) if OK, SIG_ERR on error
=typedef void sigfunction (int);sigfunction *signal(int, sa_handler *);SIG_ERRSIG_DFLSIG_IGN
signal C library ANSI C
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
void catchint(int);
signal(SIGINT,catchint);
printf(“sleep call #1\n”); sleep(4);
printf(“sleep call #2\n”); sleep(4);
printf(“Exiting \n”); exit(0);
}
void catchint(int signo) {
printf(“\nCATCHINT: signo=%d\n”, signo);
printf(“CATCHINT: returning\n\n”);
}
Ex) signal C library
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
signal sets type sigset_t <signal.h> a list of signals (to do something with)
one of the main parameters passed to system call that deal with signal
#include <signal.h>
//initialize
int sigemptyset (sigset_t *set);
int sigfillset (sigset_t *set);
//manipulate
int sigaddset (sigset_t *set, int signo);
int sigdelset (sigset_t *set, int signo);
//signo 가 set 의 member 인지 check
int sigismember(const sigset_t *set, int signo);
0 : ok-1 : error
0 : ok-1 : error
0 : non-member1 : member
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
signal sets
#include <signal.h>
sigset_t mask1, mask2;
sigemptyset(&mask1); sigaddset(&mask1, SIGINT);sigaddset(&mask1, SIGQUIT);
sigfillset(&mask2);sigdelset(&mask2, SIGCHLD);
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
sigaction system call setting the signal action Detailed signal management to choose a particular method of handling a signal
#include <signal.h>
int sigaction(int signo, const struct sigaction *act, const struct sigaction *oldact );
previous settingspecify an actionexcept) SIGSTOP
SIGKILLto set
either one can NULL
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
<signal.h>struct sigaction{ void (* sa_handler) (int); sigset_t sa_mask; int sa_flags; int (*sa_sigaction)(int, siginfo_t*, void *);} sigset_t
sa_handler: the action to be taken(SIG_IGN,SIG_DEF,func)sa_mask: to add signal blocked during sa_handlersa_flags: flags which affect the behavior of the signal
SA_RESETHAND : reset to SIG_DFL after executing sa_handler SA_SIGINFO : passing additional information to sa_sigaction
its number, sending PID, RUID of the sending PID.. Must use sa_sigaction() instead of sa_handler()
SA_RESTART : slow system call restart
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
ex) catching SIGINT
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
static struct sigaction act;
void catchint(int);
act.sa_handler = catchint;
sigfillset(&(act.sa_mask));
sigaction(SIGINT, &act, NULL);
printf(“sleep call #1\n”); sleep(4);
printf(“sleep call #2\n”); sleep(4);
printf(“sleep call #3\n”); sleep(4);
printf(“sleep call #4\n”); sleep(4);
printf(“Exiting \n”); exit(0);
}
void catchint(int signo) {
printf(“\nCATCHINT: signo=%d\n”, signo);
printf(“CATCHINT: returning\n\n”);
}
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
ex) ignoring SIGINT
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
static struct sigaction act;
act.sa_handler = SIG_IGN;
sigfillset(&(act.sa_mask));
sigaction(SIGINT, &act, NULL);
sigaction(SIGQUIT, &act, NULL);
printf(“sleep call #1\n”); sleep(4);
printf(“sleep call #2\n”); sleep(4);
printf(“sleep call #3\n”); sleep(4);
printf(“sleep call #4\n”); sleep(4);
printf(“Exiting \n”); exit(0);
}
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
ex) restoring a previous action
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
int main() {
static struct sigaction act, oldact;
void catchint(int);
act.sa_handler = catchint;
sigfillset(&(act.sa_mask));
//step1 : signal disposition 설정 sigaction(SIGINT, &act, NULL);
sleep(4);
printf(“sleep call #1\n”); sleep(4);
//step2 : step1 에서 설정한 signal disposition 을 저장 sigaction(SIGINT, NULL, &oldact);
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
ex) restoring a previous action (cont’d)
act.sa_handler = SIG_IGN;
sigfillset(&(act.sa_mask));
//step3 : signal disposition 재설정 sigaction(SIGINT, &act, NULL); sigaction(SIGINT, &act, &oldact);
printf(“sleep call #2\n”); sleep(4);
printf(“sleep call #3\n”); sleep(4);
//step2 에서 저장했던 signal disposition 을 다시 복원 sigaction(SIGINT, &oldact, NULL);
printf(“sleep call #4\n”); sleep(4);
printf(“Exiting \n”); exit(0);
}
void catchint(int signo) {
printf(“\nCATCHINT: signo=%d\n”, signo);
printf(“CATCHINT: returning\n\n”);
}
2007 UNIX Programming2007 UNIX Programming
signal handlingsignal handling
ex) a graceful exit
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int main(){
static struct sigaction act;
void g_exit(int);
act.sa_handler = g_exit;
sigaction(SIGINT, &act, NULL);
……… //tempfile 조작 }
void g_exit(int s) {
unlink(“tempfile”);
fprintf(stderr, “Interrupted – exiting\n”);
exit(1);
}
2007 UNIX Programming2007 UNIX Programming
Signals and System CallsSignals and System Calls
If a process is sent a signal when it is executing a system call Default action
the signal has no effect until the system call completes
Exception Slow system calls : read(), write(), open() etcReturn errno (errno = EINTR)
example for interrupted system calls
if(write(tfd, buf, size) < 0 ){
if(errno == EINTR){
fprintf(stderr,”write interrupted\n”);
}
/* handle other errors */
}
2007 UNIX Programming2007 UNIX Programming
Signals and system callsSignals and system calls
Solution for interrupted slow system calls Solution 1
Solution2sa_flags of struct sigaction : setting SA_RESTARTEx)
act.sa_flags |= SA_RESTART
again:
if(write(tfd, buf, size) < 0 ){
if(errno == EINTR){
fprintf(stderr,”write interrupted\n”);
goto again; // just an interrupted system call
}
/* handle other errors */
}
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
Blocked Signal Not delivered to process When the signal is unblocked, it is delivered to process Don’t the block SIGKILL and SIGSTOP
Signal maskThe collection of signals that are currently blocked
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
returns the set of signals that are blocked from delivery and currently pending for the calling process
The set of signals is returned through the set argument
#include <signal.h>
int sigpending(sigset_t *set);set : the set of signals that are pending
Returns : 0 if OK, -1 on error
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
to block out specific signals
#include <signal.h>
int sigprocmask (int how, const sigset_t *set, sigset_t *oldset);
SIG_SETMASK Use set for the mask- ignore the previous value of the mask
SIG_UNBLOCK Unblock the signals in set- remove them from the existing mask
SIG_BLOCK Block the signals in set- add them to the existing mask. The new mask
is the union of the existing mask and set
if set ≠ NULL
≠ NULL : previous signal mask
NULL : not used
0: ok-1 : error
2007 UNIX Programming2007 UNIX Programming
Signal blockingSignal blocking
Print the signal mask for the process
void pr_mask() { sigset_t sigset; int errno_save;
errno_save = errno;
if(sigprocmask(SIG_SETMASK, NULL, &sigset) < 0) perror(“sigprocmask error”);
if(sigismember(&sigset, SIGINT)) printf(“SIGINT ”); if(sigismember(&sigset, SIGQUIT)) printf(“SIGQUIT ”); if(sigismember(&sigset, SIGUSR1)) printf(“SIGUSR1 ” ); if(sigismember(&sigset, SIGALRM)) printf(“SIGALRM ”);
printf(“\n”);}
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
Ex) extremely critical code
#include <signal.h>
...
sigset_t set1;
sigfillset(&set1);
sigprocmask(SIG_SETMASK, &set1, NULL);...
/* perform extremely critical code */...sigprocmask(SIG_UNBLOCK, &set1, NULL);
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
Ex) less critical piece of code
#include <signal.h>
sigset_t set1, set2;
sigfillset(&set1);
sigfillset(&set2);
sigdelset(&set2, SIGINT);
sigdelset(&set2, SIGQUIT);
/* perform non critical code */
sigprocmask(SIG_SETMASK, &set1, NULL);
/* perform extremely critical code */
sigprocmask(SIG_UNBLOCK, &set2, NULL);
/* perform less critical code */
sigprocmask(SIG_UNBLOCK, &set1, NULL);
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
Signal blocking with fork and exec
#include <errno.h>#include <stdio.h>#include <signal.h>#include <unistd.h>#include <sys/types.h>#include <sys/wait.h>
void catchctrlc(int signo){printf("interupted %ld - %d\n", getpid(), signo);
}
int main(){pid_t child;sigset_t mask,omask;
struct sigaction act;
//SIGINT 로 signal mask 설정if((sigemptyset(&mask) == -1) || (sigaddset(&mask,SIGINT)== -1) ||
(sigprocmask(SIG_SETMASK,&mask,&omask) == -1)) {perror("sigprocmask");return 1;
}
act.sa_handler = catchctrlc; sigfillset(&(act.sa_mask));
sigaction(SIGINT, &act,NULL);
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
Signal blocking with fork and execif((child=fork()) == -1)
return 1;
if(child == 0){
sleep(14);execl("/bin/ls","ls","-l",NULL);perror("execl");return 1;
}
sleep(5);//unblocked SIGINTif(sigprocmask(SIG_SETMASK, &omask, NULL) == -1){
return 1;
}
while(wait(NULL) == -1){if(errno != EINTR) {
perror("error");return 1 ;
}}return 0;
}
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
pause system call to pause the calling process until any signal Obsolete by sigsuspend system call
#include <unistd.h> #include <signal.h> void sig_handler(int signo){ printf("SIGINT 발생 \n"); }int main(){ static struct sigaction act; act.sa_handler = sig_handler; sigfillset(&(act.sa_mask)); sigaction(SIGINT, &act, NULL); printf("hello world!\n"); pause(); printf("Interupt\n");}
#include <unistd.h>
int pause ();Returns : -1 with errno set to EINTR
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
Reliability Problem of pause system call
if(!usr_interrupt)pause();
sigset_t newmask, oldmask;sigemptyset(&newmask);sigaddset(&newmask, SIGINT);
/* block SIGINT and save current signal mask */sigprocmask(SIG_BLOCK, &newmask, &oldmask);../* critical region of code */../* reset signal mask, which unblocks SIGINT */sigprocmask(SIG_SETMASK, &oldmask, NULL);
/* window is open */pause(); /*wait for signal to occur */
Unblock 된 Signal 이 발생한다면 ?
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
A way to both reset the signal mask and put the process to sleep in a single atomic operation
Replace the caller’s signal mask with the set of signals pointed to by the sigmask argument
Suspend the caller until delivery of a signal whose action is either to execute a signal catching function or to terminate the process
If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend
#include <signal.h>
int sigsuspend(const sigset_t *sigmask)sigmask : blocked signal (usually empty set)Returns : -1 with errno set to EINTR(OK)
-1 with errno set to EFAULT(error)
2007 UNIX Programming2007 UNIX Programming
signal blockingsignal blocking
int main(void) {signal(SIGINT, sig_int);sigemptyset(&zeromask);sigaddset(&zeromask, SIGUSR1);sigemptyset(&newmask);sigaddset(&newmask, SIGINT);sigprocmask(SIG_BLOCK, &newmask, &oldmask);
/* critical region of code */
/* pause, allowing all signals except SIGUSR1 */sigsuspend(&zeromask);sigprocmask(SIG_SETMASK, &oldmask, NULL);
exit(0);}
static void sig_int(int signo) {return;
}
2007 UNIX Programming2007 UNIX Programming
sending signalsending signal
send a signal to other process or a group kill UNIX command
Signal used mainly SIGHUP(1), SIGINT(2), SIGQUIT(3), SIGKILL(9), SIGTERM(15)
Ex)
kill -2 100kill –s int 100kill –s INT 100kill –INT 100
kill –s signal_name pid…kill [-signal_name] pid….kill [-signal_number] pid…
2007 UNIX Programming2007 UNIX Programming
sending signalsending signal
send a signal to other process or a group kill system call
#include <sys/types.h>#include <signal.h>
int kill (pid_t pid, int sig);
0 : ok-1 : errorEPERM : permissionESRCH : no such processEINVAL : sig is not valid
> 0 : to certain process= 0 : to all process in own process group= -1 : if euid = root, all process except init process if euid = user, all process with a ruid equal to euid of the sender
< 0 : to all process in |pid| process group
> 0 : certain signal= 0 : normal error checking
2007 UNIX Programming2007 UNIX Programming
sending signalsending signal
raise to send a signal to itself
#include <signal.h>
int raise (int sig); [ = kill(getpid(), sig); ]
#include <unistd.h>
unsigned int alarm (unsigned int secs);
0 : not setting any pervious alarm timer>0 :time remaining for any previous alarm timer
in seconds
alarm to set a timer (timer expire : SIGALRM) alarm(0) : alarm turned off Not supported multiple alarm
2007 UNIX Programming2007 UNIX Programming
sending signalsending signal
static void sig_alarm(int signo) {
/* nothing to do, just return to wake up the pause */return ;
}
unsigned int sleep1(unsigned int nsecs) { if(signal(SIGALRM, sig_alarm) == SIG_ERR) return (nsecs);
alarm(nsecs); /* start the timer */ pause(); /* next caught signal wakes us up */ return (alarm(0)); /* turn off timer, return unslept time */}
Simple, incomplete implementation of a sleep
2007 UNIX Programming2007 UNIX Programming
sigsetjmp and siglongjmpsigsetjmp and siglongjmp
When a signal is caught, the signal-catching function is entered with the current signal automatically being added to the signal mask of the process prevents subsequent occurrence of that signal from interrupting the
signal handler
If savemask is nonzero then sigsetjmp saves the current signal mask of the process in env
When siglongjmp is called, if the env argument was saved by a call to sigsetjmp with a nonzero savemask, then siglongjmp restores the saved signal mask
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savemask);Returns : 0 if called directly, nonzero if returning from a call to siglongjmp
void siglongjmp(sigjmp_buf env, int val);
2007 UNIX Programming2007 UNIX Programming
sigsetjmp and siglongjmpsigsetjmp and siglongjmp
sigsetjmp_buf position;void goback(int);
int main(void) {static struct sigaction act;.../* save current position */if(sigsetjmp(position, 1) == 0){act.sa_handler = goback;sigaction(SIGINT,&act, NULL);}
domenu();..
}
void goback(int signo) {write(2, “\nInterrupt\n”);/* go back to saved position */siglongjmp(position,1);
}
2007 UNIX Programming2007 UNIX Programming
sigsetjmp and siglongjmpsigsetjmp and siglongjmp
int main(void) {signal(SIGUSR1, sig_usr1);signal(SIGALRM, sig_alrm);
if(sigsetjmp(jmpbuf,1)) {exit(1);
}canjump = 1;for(;;) pause();
}
static void sig_usr1(int signo) {if(canjmp ==0) return;
alarm(3);for(;;)... /* busy wait for 3 seconds */
canjump = 0;siglongjmp(jmpbuf,1);
}
static void sig_alrm(int signo) {return;
}
2007 UNIX Programming2007 UNIX Programming
sigsetjmp and siglongjmpsigsetjmp and siglongjmp
static jmp_buf env_alrm;
static void sig_alrm(int signo) { setlongjmp(env_alrm,1);}
unsigned int sleep2(unsigned int nsecs) { if(signal(SIGALRM, sig_alrm) == SIG_ERR) return (nsecs);
if( sigsetjmp(env_alrm,1) == 0) { alarm(nsecs); pause(); } return (alarm(0));}
Another (imperfect) implementation of a sleep
top related