1 / 40

[Unix Programming] Signal and Signal Processing

[Unix Programming] Signal and Signal Processing. Young-Ju, Han Email: yjhan@imtl.skku.ac.kr. Contents. Introduction signal names normal and abnormal termination signal handling signal sets setting the signal action : signal & sigaction Signal blocking Sending signals

azure
Télécharger la présentation

[Unix Programming] Signal and Signal Processing

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. [Unix Programming]Signal and Signal Processing Young-Ju, Han Email: yjhan@imtl.skku.ac.kr

  2. Contents • 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 Programming

  3. Introduction • 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 Programming

  4. Introduction • signal name 2007 UNIX Programming

  5. Introduction 2007 UNIX Programming

  6. Introduction • abnormal termination • SIGABRT, SIGBUS, SIGSEGV, SIGQUIT, SIGILL, SIGTRAP, SIGSYS, SIGXCPU, SIGXFSZ, SIGFPE • core 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 signal • core dump • a process can send a signal to itself 2007 UNIX Programming

  7. signal 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 discarded • never be ignored: SIGKILL, SIGSTOP • Let the default action apply • terminate process (abnormal terminate) • ignore (SIGCHLD ) • stop (SIGSTOP,SIGSTP) • catch the signal • take a specified user-defined action • to perform clean-up operation • Never be catched: SIGKILL, SIGSTOP 2007 UNIX Programming

  8. signal handling • signal C library • ANSI C • 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_ERR SIG_DFL SIG_IGN 2007 UNIX Programming

  9. signal handling • Ex) signal C library #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”); } 2007 UNIX Programming

  10. signal 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);//manipulateint 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-member 1 : member 2007 UNIX Programming

  11. signal 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 Programming

  12. signal 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 ); specify an action except) SIGSTOP SIGKILL previous setting to set either one can NULL 2007 UNIX Programming

  13. signal 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_handler • sa_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 Programming

  14. signal handling • ex) catching SIGINT void catchint(int signo) { printf(“\nCATCHINT: signo=%d\n”, signo); printf(“CATCHINT: returning\n\n”); } #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); } 2007 UNIX Programming

  15. signal 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 Programming

  16. signal 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 Programming

  17. signal 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 Programming

  18. signal 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 Programming

  19. Signals 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() etc • Return 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 Programming

  20. Signals and system calls • Solution for interrupted slow system calls • Solution 1 • Solution2 • sa_flags of struct sigaction : setting SA_RESTART • Ex) • 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 Programming

  21. signal 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 mask • The collection of signals that are currently blocked 2007 UNIX Programming

  22. signal blocking #include <signal.h> int sigpending(sigset_t *set); set : the set of signals that are pending Returns : 0 if OK, -1 on error • 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 2007 UNIX Programming

  23. signal blocking • to block out specific signals #include <signal.h> int sigprocmask (int how, const sigset_t *set, sigset_t *oldset); ≠ NULL : previous signal mask NULL : not used 0: ok -1 : error if set ≠ NULL 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 2007 UNIX Programming

  24. Signal 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 Programming

  25. signal 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 Programming

  26. signal 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 Programming

  27. signal 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 Programming

  28. signal blocking • Signal blocking with fork and exec if((child=fork()) == -1) return 1; if(child == 0){ sleep(14); execl("/bin/ls","ls","-l",NULL); perror("execl"); return 1; } sleep(5); //unblocked SIGINT if(sigprocmask(SIG_SETMASK, &omask, NULL) == -1){ return 1; } while(wait(NULL) == -1){ if(errno != EINTR) { perror("error"); return 1 ; } } return 0; } 2007 UNIX Programming

  29. signal blocking • pause system call • to pause the calling process until any signal • Obsolete by sigsuspendsystem call #include <unistd.h> int pause (); Returns : -1 with errno set to EINTR #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");} 2007 UNIX Programming

  30. signal 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 Programming

  31. signal blocking #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) • 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 2007 UNIX Programming

  32. signal 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 Programming

  33. sending 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 –s signal_name pid… kill [-signal_name] pid…. kill [-signal_number] pid… kill -2 100 kill –s int 100 kill –s INT 100 kill –INT 100 2007 UNIX Programming

  34. sending 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 : error EPERM : permission ESRCH : no such process EINVAL : 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 Programming

  35. sending signal • raise • to send a signal to itself #include <signal.h> int raise (int sig); [ = kill(getpid(), sig); ] • alarm • to set a timer (timer expire : SIGALRM) • alarm(0) : alarm turned off • Not supported multiple alarm #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 2007 UNIX Programming

  36. sending signal • Simple, incomplete implementation of a sleep 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 */ } 2007 UNIX Programming

  37. sigsetjmp and siglongjmp #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); • 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 2007 UNIX Programming

  38. sigsetjmp and siglongjmp void goback(int signo) { write(2, “\nInterrupt\n”); /* go back to saved position */ siglongjmp(position,1); } 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(); . . } 2007 UNIX Programming

  39. sigsetjmp and siglongjmp static void sig_alrm(int signo) { return; } 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); } 2007 UNIX Programming

  40. sigsetjmp and siglongjmp • Another (imperfect) implementation of a sleep 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)); } 2007 UNIX Programming

More Related