Presentation is loading. Please wait.

Presentation is loading. Please wait.

CHAPTER 10. SIGNALS System Programming 本份投影片大量參考熊博安教授的系統程式投影片 羅習五 國立中正大學資訊工程學系 EA-001 (05)2720411 ext.

Similar presentations


Presentation on theme: "CHAPTER 10. SIGNALS System Programming 本份投影片大量參考熊博安教授的系統程式投影片 羅習五 國立中正大學資訊工程學系 EA-001 (05)2720411 ext."— Presentation transcript:

1 CHAPTER 10. SIGNALS System Programming 本份投影片大量參考熊博安教授的系統程式投影片 羅習五 國立中正大學資訊工程學系 shiwulo@cs.ccu.edu.twshiwulo@cs.ccu.edu.twClass: EA-001 (05)2720411 ext. 33116Office: EA-517

2 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 2 Introduction Signals are software interrupts Handles asynchronous events user typing CTRL-C to stop a program next program in pipeline terminated prematurely Most implementations of signals were reliable and POSIX.1 standardized them

3 What is “signal” 3 user land kernel land system call signal (up call) hardware/software events kernel service

4 What is “signal” 4 time register a call back function my_sig_handler eventfunc div by 0default seg. faultdefault alarmmy_sig_handler ctr+cterminate ctr+/terminate

5 What is “signal” 5 time register a call back function my_sig_handler eventfunc div by 0default seg. faultdefault alarmmy_sig_handler ctr+cterminate ctr+/terminate

6 What is “signal” 6

7 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 7 Signal Concepts Every signal has a name. All begin with SIG. For example, SIGABRT : abort signal from abort() SIGALRM : alarm signal from alarm() These names are all defined by positive integer constants in the header

8 Signal Generation Terminal-generated signals: SIGINT Generated by hardware exceptions: SIGFPE: divide by 0 SIGSEGV: invalid memory reference Process generated signal kill(): send any signal to a process or process group (owner, superuser!) kill command: interface to kill() Software conditions: SIGURG: out-of-band network data SIGPIPE: pipe-write after pipe reader is terminated SIGALRM: alarm clock expires Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 8

9 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 9 Signal Disposition (Action) 1. IGNORE SIGNAL: all signals can be ignored, except SIGKILL and SIGSTOP Kernel or superuser can kill or stop a process, or Hardware exceptions leave process behavior undefined if signals ignored 2. CATCH SIGNAL: Call a function of ours when a signal occurs. Own shell: SIGINT  return to main() Child terminated: SIGCHLD  waitpid() Temporary files: SIGTERM  clean up 3. DEFAULT ACTION: most are to terminate process (see next Figure!)

10 UNIX Signals (BSD) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 10

11 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 11 UNIX Signals SIGABRT : signal from abort(), process terminates abnormally SIGALRM : timer set with alarm() expires SIGBUS : hardware fault (memory) SIGCHLD : child terminated, default action = ignore SIGCONT : sent to a stopped process to continue (default action), vi catches this signal to redraw terminal screen SIGEMT : hardware fault SIGFPE : arithmetic exception (floating point error; e.g, div by 0)

12 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 12 UNIX Signals SIGHUP : disconnect detected, session leader terminates, daemon processes reread configuration files SIGILL : Illegal hardware instruction SIGINFO : Terminal driver generates signal when we type status key (CTRL-T) SIGINT : Terminal driver generates signal when we type interrupt key (CTRL-C) SIGIO : Asynchronous I/O event

13 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 13 UNIX Signals SIGIOT : hardware fault (I/O trap) SIGKILL : to kill process by admin (cannot be caught or ignored) SIGPIPE : pipe write after pipe reader has terminated (same for socket) SIGPOLL : Specific event on pollable device SIGPROF : Profiling interval timer (set by setitimer) has expired

14 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 14 UNIX Signals SIGPWR : uninterruptible power supply (UPS) notifies a process of low power condition SIGQUIT : Terminal driver generates signal when we type quit key (CTRL-\) SIGSEGV : invalid memory reference SIGSTOP : Job-control signal to stop process, cannot be caught or ignored SIGSYS : invalid system call SIGTERM : termination signal sent by kill

15 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 15 UNIX Signals SIGTRAP : hardware fault (trap to debugger) SIGTSTP : Terminal driver generates signal when we type suspend key (CTRL-Z) SIGTTIN : background process tries to read from controlling terminal SIGTTOU : background process tries to write to controlling terminal SIGURG : urgent condition has occurred (out-of-band network data) SIGUSR1 : user-defined for API SIGUSR2 : user-defined for API

16 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 16 UNIX Signals SIGVTALRM : virtual interval timer set by setitimer(2) expired SIGWINCH : ioctl() changes window size SIGXCPU : process exceeds soft CPU time limit SIGXFSZ : process exceeds soft file size limit NULL signal: If signo is 0 the call does not send a signal, but it still performs error checking to test whether a process has suitable permissions to send the provided process a signal.

17 signal and process management Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 17 http://linux.vbird.org/linux_basic/0440processcontrol.php

18 signal Function #include void (*signal(int signo, void (*func)(int))) (int); Returns: previous disposition of signal if OK, SIG_ERR on error signo: SIGXXX signal name func: SIG_IGN, or SIG_DFL, or user-defined function (signal handler) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 18

19 Figure 10.2: signal Function 1.#include “apue.h" 2. 3.static void sig_usr(int); /*handler for both signals*/ 4. 5.int main(void) { 6. if (signal(SIGUSR1, sig_usr) == SIG_ERR) 7. err_sys("can't catch SIGUSR1"); 8. if (signal(SIGUSR2, sig_usr) == SIG_ERR) 9. err_sys("can't catch SIGUSR2"); 10. for ( ; ; ) pause(); 11.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 19

20 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 20 Figure 10.2: signal Function 1.static void 2.sig_usr(int signo)/* argument is signal number */ 3.{ 4. if (signo == SIGUSR1) 5. printf("received SIGUSR1\n"); 6. else if (signo == SIGUSR2) 7. printf("received SIGUSR2\n"); 8. else err_dump("received signal %d\n", signo); 9. return; 10.}

21 Figure 10.2: results $./a.out & /* “&” make the process as a background process*/ [1] 7216 $ kill –USR1 7216 received SIGUSR1 $ kill –USR2 7216 received SIGUSR2 $ kill 7216 (SIGTERM not caught) [1] + Terminated./a.out Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 21

22 Lab 1 列印所有的 signal 1. #include 2. #include 3. #include 4. void sighandler(int signumber) { 5. printf("get a signal named '%d', '%s'\n", signumber, 6. sys_siglist[signumber]); 7. } 8. int main(int argc, char **argv) { 9. int sig_exist[100]; 10. int idx = 0; 11. for (idx = 0; idx < 100; idx++) { 12. if (signal(idx, sighandler) == SIG_ERR) { 13. sig_exist[idx] = 0; 14. } else { 15. sig_exist[idx] = 1; 16. } 17. } 18. for (idx = 0; idx < 100; idx++) { 19. if (sig_exist[idx] == 1) 20. printf("%2d %s\n", idx, sys_siglist[idx]); 21. } 22. printf("my pid is %d\n", getpid()); 23. printf("press any key to resume\n"); 24. getchar(); 25. } Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 22

23 make your code more readable $man indent The indent program can be used to make code easier to read. It can also convert from one style of writing C to another An Example /*a compact style*/ indent -kr -br -brf lab1.c 23

24 Lab 1: results (MAC OS X) 1 Hangup 2 Interrupt 3 Quit 4 Illegal instruction 5 Trace/BPT trap 6 Abort trap 7 EMT trap 8 Floating point exception 10 Bus error 11 Segmentation fault 12 Bad system call 13 Broken pipe 14 Alarm clock 15 Terminated 16 Urgent I/O condition 18 Suspended 19 Continued 20 Child exited 21 Stopped (tty input) 22 Stopped (tty output) 23 I/O possible 24 Cputime limit exceeded 25 Filesize limit exceeded 26 Virtual timer expired 27 Profiling timer expired 28 Window size changes 29 Information request 30 User defined signal 1 31 User defined signal 2 Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 24

25 Lab 1: results (Linux) 1 Hangup 2 Interrupt 3 Quit 4 Illegal instruction 5 Trace/breakpoint trap 6 Aborted 7 Bus error 8 Floating point exception 10 User defined signal 1 11 Segmentation fault 12 User defined signal 2 13 Broken pipe 14 Alarm clock 15 Terminated 16 Stack fault 17 Child exited 18 Continued 20 Stopped 21 Stopped (tty input) 22 Stopped (tty output) 23 Urgent I/O condition 24 CPU time limit exceeded 25 File size limit exceeded 26 Virtual timer expired 27 Profiling timer expired 28 Window changed 29 I/O possible 30 Power failure 31 Bad system call 34 (null) 35 (null) 36 (null) 37 (null) 38 (null) 39 (null) 40 (null) 41 (null) 42 (null) 43 (null) 44 (null) 45 (null) 46 (null) 47 (null) 48 (null) 49 (null) 50 (null) 51 (null) 52 (null) 53 (null) 54 (null) 55 (null) 56 (null) 57 (null) 58 (null) 59 (null) 60 (null) 61 (null) 62 (null) 63 (null) 64 (null) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 25

26 Lab 1: results (Linux) 試試看 1. kill -4 uid 2. resize your terminal window 26

27 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 27 Program Start-up exec signals being caught  default action (old handler has no meaning in new program) all other signals  left alone gcc main.c & the shell automatically sets the disposition of the interrupt and quit signals in the background process to be ignored.

28 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 28 Signal disposition on fork On fork: Child inherits parent ’ s signal dispositions Old signal handler has meaning in child

29 unreliable signal??? Currently, most UNIX-like OSes support reliable signal. Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 29

30 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 30 Interrupted System Calls A process is blocked in a “ slow ” device (a system call) The process receives a signal The system call is interrupted and returns an error ( errno = EINTR ) May be something happened that should wake up the blocked system call

31 Why? 31 rdyQ running interruptible uninterruptible fork()_exit()

32 Interrupted System Calls System calls divided into 2 categories: slow: reads from or writes to files that can block caller forever (pipes, terminals, network devs) opens of files that block until some condition occurs (terminal waiting on modem answer) pause, wait some ioctl operations interprocessor communication all others: disk I/O, etc. Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 32

33 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 33 Interrupted System Calls Need to restart an interrupted system call 1.again: 2. if ( (n=read(fd, buf, BUFFSIZE)) < 0) { 3. if (errno==EINTR) goto again; 4. /* handle other errors */ 5. }

34 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 34 Interrupted System Calls POSIX.1 Allows implementation to restart interrupted system calls, but not required Single UNIX Spec (XSI extension) SA_RESTART flag to allow applications to request restart of interrupted system calls “Linux supports SA_RESTART”

35 Lab1: strace a.out rt_sigaction(SIGHUP, {0x4006ec, [HUP], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGINT, {0x4006ec, [INT], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGQUIT, {0x4006ec, [QUIT], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGILL, {0x4006ec, [ILL], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGTRAP, {0x4006ec, [TRAP], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGABRT, {0x4006ec, [ABRT], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGBUS, {0x4006ec, [BUS], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGFPE, {0x4006ec, [FPE], SA_RESTORER|SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGKILL, {0x4006ec, [KILL], SA_RESTORER| SA_RESTART, 0x7fa1045af4a0}, {SIG_DFL, [], 0}, 8) = -1 EINVAL (Invalid argument) 35

36 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 36 Interrupted System Calls

37 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 37 Reentrant Functions 1. Process is executing 2. Signal arrives and is caught 3. Signal handler starts executing 4. Signal handler returns 5. Process resumes execution summary: signal is an asynchronous event. so... Any problem?

38 38 time register a call back function my_sig_handler eventfunc div by 0default seg. faultdefault alarmmy_sig_handler ctr+cterminate ctr+/terminate

39 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 39 Reentrant Functions What if process was in the middle of malloc(), signal handler starts executing and also calls malloc()? malloc() maintains a linked list of all allocated areas process may have been in the middle of updating the linked list!

40 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 40 Reentrant Functions Functions that can be called by two or more processes (tasks, signal handlers), with arbitrary preemption (interrupt), and still give the same predictable output results. Use static variables in an atomic way, Do not call malloc or free, Does not belong to standard I/O library Reentrancy Conditions

41 Reentrant Functions (Linux) _exit accept access aio_error aio_return aio_suspend alarm bind bort cfgetispeed cfgetospeed cfsetispeed cfsetospeed chdir chmod chown clock_getti me close connect creat dup dup2 execle execve Exit fchmod fchown fcntl fdatasync fork fpathconf fstat fsync ftruncate getegid geteuid getgid getgroups getpeername getpgrp getpid getppid getsockname getsockopt getuid kill link listen lseek lstat mkdir mkfifo open pathconf pause pipe poll posix_trace _event pselect raise read readlink recv recvfrom recvmsg rename rmdir select sem_post send sendmsg sendto setgid setpgid setsid setsockopt setuid shutdown sigaction sigaddset sigdelset sigemptyset sigfillset sigismember signal sigpause sigpending sigprocmask sigqueue sigset sigsuspend sleep socket stat symlink tcdrain tcflow tcgetattr tcgetpgrp tcsetattr tcsetpgrp timer_getov errun timer_getti me times umask unlink utime wait waitpid write Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 41

42 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 42 Reentrant Functions Signal handlers should only call reentrant functions! “ errno variable” updated by reentrant functions such as read(), wait(), etc. signal handler should save errno, and restore it on exit

43 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 43 Figure 10.5: nonreentrant function call in signal handler 1.#include 2.#include “apue.h” 3.static void my_alarm(int); 4.int main(void) { 5. struct passwd *ptr; 6. 7. signal(SIGALRM, my_alarm); 8. alarm(1); 9. 10. for ( ; ; ) { 11. if ( (ptr = getpwnam("sar")) == NULL) 12. err_sys("getpwnam error"); Generates SIGALRM after 1 sec

44 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 44 Figure 10.5: nonreentrant function call in signal handler 1. if (strcmp(ptr->pw_name, "sar") != 0) 2. printf("return value corrupted!, pw_name = %s\n", 3. ptr->pw_name); 4. } 5.} 6. 7.static void 8.my_alarm(int signo) 9.{ 10. struct passwd *rootptr; 11. 12. printf("in signal handler\n"); 13. if ( (rootptr = getpwnam("root")) == NULL) 14. err_sys("getpwnam(root) error"); 15. alarm(1); 16.} A NONREENTRANT function called by both main() and signal handler

45 Figure 10.5: results Results are random Usually terminated by SIGSEGV Internal pointers corrupted when signal handler also called getpwnam() after main called it Sometimes terminated correctly, but return value sometimes corrupted and sometimes fine. 在 Linux 當中,這段程式碼幾乎不會有任何問題,但... 萬一... 不怕一萬,只怕萬一 Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 45

46 SIGCLD Semantics signal(SIGCLD, SIG_IGN) no zombie processes for children subsequent wait() will block until all children terminated and returns -1 with errno = ECHILD different from SIG_DFL (also ignore, but without the above semantics) signal(SIGCLD, handler) kernel checks for child to be waited for if there is, kernel calls SIGCLD handler Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 46

47 SIGCHLD Semantics POSIX.1 Does not specify what happens when SIGCHLD is ignored Single UNIX Specification (XSI extension) Same as for SIGCLD 4.4BSD and FreeBSD 5.2.1 Always generates zombies if SIGCHLD ignored SVR4, Solaris 9, Linux, Mac OS X 10.3 signal(SIGCHLD, SIG_IGN)  zombies never generated Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 47

48 Figure 10.6: SIGCLD handler not working in System V 在目前的UNIX應該不會出現這個現象 如果於處理SIGCLD的signal內再呼叫signal 而出現問題時 請參考此章節 Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 48

49 這個問題類似 不用死記... 龘:三個「龍」唸ㄊㄚˋ 麤:三個「鹿」唸ㄘㄨ 驫:三個「馬」唸ㄅㄧㄠ 馫:三個「香」唸ㄒㄧㄥ 就算我們精通華文,上面的這些字也多半念不出來 有些東西,仿佛記得就好,不會再查書 49

50 Reliable Signal Terminology and Semantics Kernel sets a flag in the process table indicating that the signal is generated Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 50

51 Reliable Signal Terminology and Semantics Signal is DELIVERED to a process if action for signal is taken Between generation and delivery, signal is called PENDING A process can BLOCK the delivery of a signal using SIGNAL MASK Signal mask can be changed by sigprocmask() (see Section 10.12) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 51

52 Reliable Signal Terminology and Semantics More than one blocked signal? Queued? No! Just once! SIGSEGV delivered first sigset_t: POSIX.1 data type to store signal mask #bits = #signals, Bit i = 1  signal i blocked Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 52

53 Lab5 #include void sighandler(int signumber) { printf("get a signal named '%d', '%s'\n", signumber, sys_siglist[signumber]); if (signumber == SIGINT) exit(0); } int main(int argc, char **argv) { int sig_exist[100]; sigset_t sigset; int idx = 0; for (idx = 0; idx < 100; idx++) { if (signal(idx, sighandler) == SIG_ERR) { sig_exist[idx] = 0; } else { sig_exist[idx] = 1; } for (idx = 0; idx < 100; idx++) { if (sig_exist[idx] == 1) printf("%2d %s\n", idx, sys_siglist[idx]); } printf("my pid is %d\n", getpid()); sigfillset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); printf("sleep 10sec\n"); for(idx=0; idx<10; idx++) { sleep(1); write(1, "*", 1); } printf("\n"); sigemptyset(&sigset); sigprocmask(SIG_SETMASK, &sigset, NULL); while (1) { pause(); } 53

54 Lab5: results... 63 (null) 64 (null) my pid is 7276 sleep 10sec *^\^\^\^\*^\^\^\^\**^\*^\***** get a signal named '3', 'Quit' ^Cget a signal named '2', 'Interrupt' 54

55 kill and raise functions kill: To send a signal to a process or a process group #include int kill(pid_t pid, int signo); Both return: 0 if OK, -1 on error Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 55

56 kill(pid_t pid, int signo) pid > 0: sent to PID==pid pid < 0: sent to PGID==|pid| pid == 0: sent to all processes with PGID == PGID of sender (with perm) pid == -1: all processes on the system for which the sender has permission to send signal (excluding system processes) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 56

57 kill function Permission to send signals: Superuser: to any process Others: real/effective ID of sender must be equal to real/effective ID of receiver Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 57

58 alarm Function alarm() sets a timer to expire at a specified time in future when timer expires, SIGALRM signal is generated default action: terminate process #include unsigned int alarm(unsigned int seconds); Returns: 0 or #seconds until previously set alarm Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 58

59 alarm Function Process receives signal after the specified seconds seconds Processor scheduling delays may occur Only 1 alarm clock per process If we call alarm, and there is a previously registered alarm not expired #seconds left for the previous alarm to expire is returned new alarm replaces previous alarm alarm(0)  a previous unexpired alarm is cancelled Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 59

60 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 60 pause Function Suspends a process until a signal is caught #include int pause(void); Returns: -1 with errno set to EINTR pause returns only if a signal handler is executed and that handler returns!

61 一些不太好的寫法 以 sleep 為例 61

62 man 3 sleep #include unsigned int sleep(unsigned int seconds); DESCRIPTION sleep() makes the calling thread sleep until seconds seconds have elapsed or a signal arrives which is not ignored. RETURN VALUE Zero if the requested time has elapsed, or the number of seconds left to sleep, if the call was interrupted by a signal handler. 62

63 Figure 10.7: using alarm and pause to implement sleep (incomplete) 1.#include 2.#include 3. 4.static void 5.sig_alrm(int signo) 6.{ 7. return; /* nothing to do, just return to wake up the pause */ 8.} 9. 10.unsigned int 11.sleep1(unsigned int nsecs) 12.{ 13. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 14. return(nsecs); 15. alarm(nsecs); /* start the timer */ 16. pause(); /* next caught signal wakes us up */ 17. return( alarm(0) ); /* turn off timer, return unslept time */ 18.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 63 假如還沒呼叫 pause 之前, alarm 就發生了?

64 Figure 10.8: Another imperfect implementation of sleep 1.#include 2.#include 3.#include 4. 5.static jmp_buf env_alrm; 6. 7.static void sig_alrm(int signo) { longjmp(env_alrm, 1); } 8. 9.unsigned int sleep2(unsigned int nsecs) { 10. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 11. return(nsecs); 12. if (setjmp(env_alrm) == 0) { 13. alarm(nsecs); /* start the timer */ 14. pause(); /* next caught signal wakes us up */ 15. } 16. return( alarm(0) ); /*turn off timer, return unslept time*/ 17.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 64

65 Figure 10.9: Calling sleep2 1.#include “apue.h" 2. 3.unsigned int sleep2(unsigned int); 4.static void sig_int(int); 5. 6.int main(void) { 7. unsigned int unslept; 8. 9. if (signal(SIGINT, sig_int) == SIG_ERR) 10. err_sys("signal(SIGINT) error"); 11. unslept = sleep2(5); 12. printf("sleep2 returned: %u\n", unslept); 13. exit(0); 14.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 65

66 Figure 10.9: Calling sleep2 1.static void sig_int(int signo) 2.{ 3. int i; 4. volatile int j; 5. 6. printf("\nsig_int starting\n"); 7. for (i = 0; i < 300000; i++) 8. for (j = 0; j < 4000; j++) 9. k += i * j; 10. /*底下這一行可能不會被呼叫到,因為在sig_alrm()中已經直 接longjmp回去*/ 11. printf("sig_int finished\n"); 12.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 66

67 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 67 Figure 10.9: results $./a.out ^? /* CTRL key pressed */ /* 照理說 ctr-c 應該打斷 sleep*/ sig_int starting /* 沒出現 “sig_int finished”*/ sleep2 returned: 0

68 活用 SIGNAL (正確、常用) 68

69 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 69 alarm: upper time limit on blocking operations A read operation on a “ slow ” device can block for a long time An upper time limit can be imposed using the alarm function and SIGALRM See next program (buggy!)

70 Figure 10.10: read with timeout 1.#include “apue.h" 2. 3.static void sig_alrm(int); 4. 5.int main(void) 6.{ 7. int n; 8. char line[MAXLINE]; 9. 10. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 11. err_sys("signal(SIGALRM) error"); 12. alarm(10); 13. if ( (n = read(STDIN_FILENO, line, MAXLINE)) < 0) 14. err_sys("read error"); 15. alarm(0); 16. 17. write(STDOUT_FILENO, line, n); 18. 19. exit(0); 20.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 70 race condition between alarm and read, set minute- long time delay to circumvent race read not interrupted if interrupted system calls are automatically restarted

71 Figure 10.10: read with timeout 1.static void 2.sig_alrm(int signo) 3.{ 4. /* nothing to do, just return to interrupt the read */ 5.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 71

72 lab6 Figure 10.10 的寫法好嗎? 當 timeout 時真的會終止 read 嗎? 是否有更好的寫法? ( hint: sigaction w/o SA_RESTART ) 72

73 Figure 10.11: read with timeout (using longjmp) 1.#include 2.#include “apue.h" 3. 4.static void sig_alrm(int); 5.static jmp_buf env_alrm; 6. 7.int 8.main(void) 9.{ 10. int n; 11. char line[MAXLINE]; 12. 13. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 14. err_sys("signal(SIGALRM) error"); 15. 16. if (setjmp(env_alrm) != 0) Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 73

74 Figure 10.11: read with timeout (using longjmp) 1.err_quit("read timeout"); 2. 3. alarm(10); 4. if ( (n = read(STDIN_FILENO, line, MAXLINE)) < 0) 5. err_sys("read error"); 6. alarm(0); 7. 8. write(STDOUT_FILENO, line, n); 9. 10. exit(0); 11.} 12. 13.static void 14.sig_alrm(int signo) 15.{ 16. longjmp(env_alrm, 1); 17.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 74 problem in interaction with other signal handlers

75 Signal Sets Signal set = a set of signals POSIX.1: sigset_t (data type to represent multiple signals) #include int sigemptyset (sigset_t *set); int sigfillset (sigset_t *set); int sigaddset (sigset_t *set, int signo); int sigdelset (sigset_t *set, int signo); Return: 0 if OK, -1 on error int sigismember (const sigset_t *set, int signo); Returns: 1 if true, 0 if false, -1 on error Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 75

76 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 76 sigprocmask Function Examine or change signals to be blocked #include int sigprocmask(int how, const sigset_t *set, sigset_t *oset); Returns: 0 if OK, -1 on error oset != NULL  current mask returned in oset set != NULL  current mask modified …

77 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 77 sigprocmask Function How to modify? (set != NULL, how = … )

78 Figure 10.14: print mask 1.#include 2.#include “apue.h" 3. 4.void pr_mask(const char *str) { 5. sigset_t sigset; 6. int errno_save; 7. 8. errno_save = errno; /*we can be called by signal handlers*/ 9. if (sigprocmask(0, NULL, &sigset) < 0) 10. err_sys("sigprocmask error"); 11. printf("%s", str); 12. if (sigismember(&sigset, SIGINT)) printf("SIGINT "); 13. if (sigismember(&sigset, SIGQUIT)) printf("SIGQUIT "); 14. if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 "); 15. if (sigismember(&sigset, SIGALRM)) printf("SIGALRM "); 16. /* remaining signals can go here */ 17. printf("\n"); 18. errno = errno_save; 19.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 78

79 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 79 sigaction Examine or modify a signal action Reliable Signals! #include int sigaction(int signo, const struct sigaction *act, struct sigaction *oact); Returns: 0 if OK, -1 on error nonnull  modify action nonnull  return action

80 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 80 sigaction 1.struct sigaction { 2./*addr of signal handler or SIG_IGN or SIG_DFL */ 3.void (*sa_handler)(int); 4./* additional signals to block */ 5.sigset_t sa_mask; 6./* signal options*/ 7.int sa_flags; 8./* alternate handler */ 9.void (*sa_sigaction)(int, siginfo_t *, void *); 10.};

81 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 81 sa_flags Check Figure 10.16 for sa_flags SA_INTERRUPT (not in standard, Linux only) SA_NOCLDSTOP (POSIX.1, all 4 platforms) SA_NOCLDWAIT (XSI, all 4 platforms) SA_NODEFER (XSI, all 4 platforms) SA_ONSTACK (XSI, all 4 platforms) SA_RESETHAND (XSI, all 4 platforms) SA_RESTART (XSI, all 4 platforms) SA_SIGINFO (POSIX.1, all 4 platforms)

82 Implementation of signal using sigaction (reliable semantics) 1.#include “apue.h" 2. 3./* Reliable version of signal(), using POSIX sigaction(). */ 4. 5.Sigfunc * 6.signal(int signo, Sigfunc *func) 7.{ 8. struct sigaction act, oact; 9. 10. act.sa_handler = func; 11. sigemptyset(&act.sa_mask); 12. act.sa_flags = 0; 13. if (signo == SIGALRM) { Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 82

83 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 83 Implementation of signal using sigaction 1.#ifdef SA_INTERRUPT 2. act.sa_flags |= SA_INTERRUPT; 3.#endif 4. } else { 5.#ifdef SA_RESTART 6. act.sa_flags |= SA_RESTART; 7.#endif 8. } 9. if (sigaction(signo, &act, &oact) < 0) 10. return(SIG_ERR); 11. return(oact.sa_handler); 12.}

84 signal (without restart) 1.#include “apue.h" 2. 3.Sigfunc * 4.signal_intr(int signo, Sigfunc *func) 5.{ 6. struct sigaction act, oact; 7. 8. act.sa_handler = func; 9. sigemptyset(&act.sa_mask); 10. act.sa_flags = 0; 11.#ifdef SA_INTERRUPT 12. act.sa_flags |= SA_INTERRUPT; 13.#endif 14. if (sigaction(signo, &act, &oact) < 0) 15. return(SIG_ERR); 16. return(oact.sa_handler); 17.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 84

85 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 85 sigsetjmp, siglongjmp Similar to setjmp and longjmp Difference: saves mask and restores it #include int sigsetjmp(sigjmp_buf env, int savemask); void siglongjmp(sigjmp_buf env, int val); Returns: 0 if called directly, nonzero if returning from siglongjmp

86 Figure 10.20: jmp functions 1.#include 2.#include 3.#include “apue.h" 4.static void sig_usr1(int), sig_alrm(int); 5.static sigjmp_buf jmpbuf; 6.static volatile sig_atomic_t canjump; 7. 8.int main(void) { 9. if (signal(SIGUSR1, sig_usr1) == SIG_ERR) 10. err_sys("signal(SIGUSR1) error"); 11. if (signal(SIGALRM, sig_alrm) == SIG_ERR) 12. err_sys("signal(SIGALRM) error"); 13. pr_mask("starting main: "); 14. 15. if (sigsetjmp(jmpbuf, 1)) { 16. pr_mask("ending main: "); 17. exit(0); } 18. canjump = 1; /* now sigsetjmp() is OK */ 19. for ( ; ; ) pause(); 20.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 86 Defined by ISO C Guaranteed atomic write (1)Does not extend across page boundaries (2)Accessed with a single machine instruction (3)Volatile: accessed by 2 threads: main and signal handler Defined by ISO C Guaranteed atomic write (1)Does not extend across page boundaries (2)Accessed with a single machine instruction (3)Volatile: accessed by 2 threads: main and signal handler

87 Figure 10.20: jmp functions 1.static void sig_usr1(int signo) { 2. time_t starttime; 3. 4. if (canjump == 0) 5. return; /* unexpected signal, ignore */ 6. 7. pr_mask("starting sig_usr1: "); 8. 9. alarm(3); /* SIGALRM in 3 seconds */ 10. 11. starttime = time(NULL); 12. for ( ; ; ) * busy wait for 5 seconds */ 13. if (time(NULL) > starttime + 5) break; 14. pr_mask("finishing sig_usr1: "); 15. 16. canjump = 0; 17. siglongjmp(jmpbuf, 1);/* jump back to main, don't return */ 18.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 87

88 Figure 10.20: jmp functions 1.static void sig_alrm(int signo) { 2. pr_mask("in sig_alrm: "); 3. return; 4.} Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 88

89 Time line for Figure 10.20 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 89

90 Figure 10.20: results $./a.out & starting main: [1] 531 $ kill –USR1 531 starting sig_usr1: SIGUSR1 $ in sig_alrm: SIGUSR1 SIGALRM finishing sig_usr1: SIGUSR1 ending main: [1] + Donea.out & Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 90

91 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 91 Without save/restore signals If we use setjmp, longjmp in Linux and Solaris, or _setjmp, _longjmp in FreeBSD, Mac OS X Final line of output: ending main: SIGUSR1 Main function is executing with SIGUSR1 blocked, after call to setjmp This is not what we want!

92 sigsuspend Function To protect critical section by blocking a signal 1.sigset_t newmask, oldmask; 2.sigemptyset(&newmask); 3.sigaddset(&newmask, SIGINT); 4.if(sigprocmask(SIG_BLOCK, &newmask, &oldmask), 0) 5. err_sys(“SIG_BLOCK error”); 6./* CRITICAL REGION OF CODE */ 7.if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 8. err_sys(“SIG_SETMASK error”); 9. 10. 11.pause(); Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 92 What if signal occurs HERE?

93 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 93 sigsuspend Function Reset signal mask & put process to sleep for a signal (1 atomic operation) #include int sigsuspend(const sigset_t *sigmask); Returns: -1 with errno set to EINTR No successful return

94 sigsuspend Function sigsuspend 的整个原子操作过程为: (1) 设置新的 mask 阻塞当前进程; (2) 收到信号,调用该进程设置的信号处理函数; (3) 待信号处理函数返回后,恢复原先 mask ; (4) sigsuspend 返回。 94 http://bbs.csdn.net/topics/290014298

95 Figure 10.22: sigsuspend 1.#include “apue.h" 2.static void sig_int(int); 3. 4.int main(void) { 5. sigset_t newmask, oldmask, waitmask; 6. pr_mask(“program start: “); 7. if (signal(SIGINT, sig_int) == SIG_ERR) 8. err_sys("signal(SIGINT) error"); 9. 10. sigemptyset(&waitmask); 11. sigaddset(&waitmask, SIGUSR1); 12. sigemptyset(&newmask); 13. sigaddset(&newmask, SIGINT); 14. /* Block SIGINT and save current signal mask */ 15. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 16. err_sys("SIG_BLOCK error"); 17. 18. /* Critical region of code */ Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 95

96 Figure 10.22: sigsuspend 1. pr_mask("in critical region: "); 2. 3. /* Pause, allowing all signals except SIGUSR1 */ 4. if (sigsuspend(&waitmask) != -1) 5. err_sys("sigsuspend error"); 6. pr_mask("after return from sigsuspend: "); 7. 8. /* Reset signal mask which unblocks SIGINT */ 9. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 10. err_sys("SIG_SETMASK error"); 11. /* And continue processing... */ 12. pr_mask(“program exit: “); 13. exit(0); 14.} 15. 16.static void sig_int(int signo) 17.{ pr_mask("\nin sig_int: "); return; } Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 96

97 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 97 Figure 10.22: results $./a.out in critical region: SIGINT ^? in sig_int: SIGINT SIGUSR1 after return from sigsuspend: SIGINT program exit: Restores mask to its value before the call to sigsuspend

98 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 98 Figure 10.23: wait for global variable using sigsuspend() 1.#include "apue.h" 2. 3.volatile sig_atomic_t quitflag; /* set nonzero by signal handler */ 4. 5.static void sig_int(int signo) 6. /* 1 signal handler for SIGINT and SIGQUIT */ 7.{ 8. if (signo == SIGINT) 9. printf("\ninterrupt\n"); 10. else if (signo == SIGQUIT) 11. quitflag = 1; /* set flag for main loop */ 12.}

99 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 99 Figure 10.23: wait for global variable using sigsuspend() 1.int main(void){ 2. sigset_t newmask, oldmask, zeromask; 3. 4. if (signal(SIGINT, sig_int) == SIG_ERR) 5. err_sys("signal(SIGINT) error"); 6. if (signal(SIGQUIT, sig_int) == SIG_ERR) 7. err_sys("signal(SIGQUIT) error"); 8. 9. sigemptyset(&zeromask); 10. sigemptyset(&newmask);

100 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 100 Figure 10.23: wait for global variable using sigsuspend() 1. sigaddset(&newmask, SIGQUIT); 2. 3. /* Block SIGQUIT and save current signal mask. */ 4. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) 5. err_sys("SIG_BLOCK error"); 6. 7. while (quitflag == 0) 8. sigsuspend(&zeromask);

101 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 101 Figure 10.23: wait for global variable using sigsuspend() 1./* SIGQUIT has been caught and is now blocked; do whatever. 2. */ 3. quitflag = 0; 4. 5. /* Reset signal mask which unblocks SIGQUIT. */ 6. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) 7. err_sys("SIG_SETMASK error"); 8. 9. exit(0); 10.}

102 Figure 10.23: results $./a.out ^? interrupt ^? interrupt ^? interrupt ^? interrupt ^? interrupt ^? interrupt ^\ $ Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 102

103 EXAMPLE 103

104 abort Function Causes abnormal program termination by sending SIGABRT to caller using raise(SIGABRT) #include void abort(void); Function never returns ISO C If SIGABRT caught and signal handler returns, abort still does not return to caller. exit, _exit, _Exit, longjmp, siglongjmp POSIX.1 Abort overrides blocking and ignoring of the signal by process Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 104

105 Implementation of POSIX.1 abort 1.#include 2.#include 3.#include 4.#include 5. 6.void abort(void) /* POSIX-style abort() function */ 7.{ 8. sigset_t mask; 9. struct sigaction action; 10. 11. /* Caller can't ignore SIGABRT, if so reset to default. */ 12. sigaction(SIGABRT, NULL, &action); 13. if (action.sa_handler == SIG_IGN) { 14. action.sa_handler = SIG_DFL; 15. sigaction(SIGABRT, &action, NULL); 16. } Slides©2006 Pao-Ann Hsiung, National Chung Cheng University, Taiwan 105

106 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 106 Implementation of POSIX.1 abort 1.if (action.sa_handler == SIG_DFL) 2. fflush(NULL); /* flush all open stdio streams */ 3. 4. /* Caller can't block SIGABRT; make sure it's unblocked. */ 5. sigfillset(&mask); 6. sigdelset(&mask, SIGABRT); /* mask has only SIGABRT turned off */ 7. sigprocmask(SIG_SETMASK, &mask, NULL); 8. 9. kill(getpid(), SIGABRT); /* send the signal */

107 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 107 Implementation of POSIX.1 abort 1./* If we're here, process caught SIGABRT and returned. */ 2. fflush(NULL); /* flush all open stdio streams */ 3. action.sa_handler = SIG_DFL; 4. sigaction(SIGABRT, &action, NULL); /* reset to default */ 5. sigprocmask(SIG_SETMASK, &mask, NULL); /* just in case... */ 6. 7. kill(getpid(), SIGABRT); /* and one more time */ 8. 9. exit(1); /* this should never be executed... */ 10.}

108 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 108 system Function Signal handling for calling system() Must ignore SIGINT, SIGQUIT Must block SIGCHLD login shell a.out/bin/sh/bin/ed fork exec fork exec fork exec background process group foreground process group

109 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 109 system Function 1. #include 2. #include 3. #include 4. #include 5. 6. /* with appropriate signal handling */ 7. int system(const char *cmdstring) { 8. pid_t pid; 9. int status; 10. struct sigaction ignore, saveintr, savequit; 11. sigset_t chldmask, savemask; 12. 13. if (cmdstring == NULL) 14. /* always a command processor with UNIX */ 15. return(1);

110 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 110 system Function 1. /*ignore SIGINT and SIGQUIT */ 2. ignore.sa_handler = SIG_IGN; 3. sigemptyset(&ignore.sa_mask); 4. ignore.sa_flags = 0; 5. if (sigaction(SIGINT, &ignore, &saveintr) < 0) 6. return(-1); 7. if (sigaction(SIGQUIT, &ignore, &savequit) < 0) 8. return(-1); 9. sigemptyset(&chldmask); /* now block SIGCHLD */ 10. sigaddset(&chldmask, SIGCHLD); 11. if (sigprocmask(SIG_BLOCK, &chldmask, &savemask) < 0) 12. return(-1);

111 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 111 system Function 1. if ((pid = fork()) < 0) { 2. /* probably out of processes */ 3. status = -1; 4. } else if (pid == 0) { /* child */ 5. /* restore previous signal actions & reset signal mask */ 6. sigaction(SIGINT, &saveintr, NULL); 7. sigaction(SIGQUIT, &savequit, NULL); 8. sigprocmask(SIG_SETMASK, &savemask, NULL); 9. 10. execl("/bin/sh", "sh", "-c", cmdstring, (char *)0); 11. _exit(127); /* exec error */ 12. }

112 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 112 system Function 1. else { /* parent */ 2. while (waitpid(pid, &status, 0) < 0) 3. if (errno != EINTR) { 4. status = -1; /* error other than EINTR from waitpid() */ 5. break; 6. } 7. } 8. /* restore previous signal actions & reset signal mask */ 9. if (sigaction(SIGINT, &saveintr, NULL) < 0) return(-1); 10. if (sigaction(SIGQUIT, &savequit, NULL) < 0) return(-1); 11. if (sigprocmask(SIG_SETMASK, &savemask, NULL) < 0) return(-1); 12. return(status); 13. }

113 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 113 sleep Function #include unsigned int sleep(unsigned int seconds); Returns 0 or number of unslept seconds Causes process to be suspended until: Amount of wall clock time specified by seconds has elapsed, OR A signal is caught by the process and the signal handler returns.

114 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 114 sleep Function 1.#include "apue.h" 2. 3.static void 4.sig_alrm(int signo) 5.{ 6. /* nothing to do, just returning wakes up sigsuspend() */ 7.}

115 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 115 sleep Function Solaris 9 Implements sleep using alarm Previously scheduled alarm is properly handled alarm(10)  3 wall clock seconds later  sleep(5)  SIGALRM received 2 seconds after waking from sleep alarm(6)  3 wall clock seconds later  sleep(5)  sleep returns in 3 seconds (not 5 seconds), return value of sleep is 2 (#unslept seconds) FreeBSD 5.2.1, Linux 2.4.22, Mac OS X 10.3 Implement sleep using nanosleep(2) (without signals, declared in Single UNIX Specification)

116 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 116 sleep Function 1.unsigned int 2.sleep(unsigned int nsecs) 3.{ 4. struct sigaction newact, oldact; 5. sigset_t newmask, oldmask, suspmask; 6. unsigned int unslept; 7. 8. /* set our handler, save previous information */ 9. newact.sa_handler = sig_alrm; 10. sigemptyset(&newact.sa_mask); 11. newact.sa_flags = 0; 12. sigaction(SIGALRM, &newact, &oldact);

117 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 117 sleep Function 1./* block SIGALRM and save current signal mask */ 2. sigemptyset(&newmask); 3. sigaddset(&newmask, SIGALRM); 4. sigprocmask(SIG_BLOCK, &newmask, &oldmask); 5. 6. alarm(nsecs); 7. 8. suspmask = oldmask; 9. /* make sure SIGALRM isn't blocked */ 10. sigdelset(&suspmask, SIGALRM); 11. /* wait for any signal to be caught */ 12. sigsuspend(&suspmask);

118 Slides©2006 Pao-Ann Hsiung, Dept of CSIE, National Chung Cheng University, Taiwan 118 sleep Function 1./* some signal has been caught, SIGALRM is now blocked */ 2. unslept = alarm(0); 3. /* reset previous action */ 4. sigaction(SIGALRM, &oldact, NULL); 5./* reset signal mask, which unblocks SIGALRM */ 6. sigprocmask(SIG_SETMASK, &oldmask, NULL); 7. return(unslept); 8.}


Download ppt "CHAPTER 10. SIGNALS System Programming 本份投影片大量參考熊博安教授的系統程式投影片 羅習五 國立中正大學資訊工程學系 EA-001 (05)2720411 ext."

Similar presentations


Ads by Google