CS33 Intro to Computer Systems XXII–1 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
CS 33Signals Part 2
CS33 Intro to Computer Systems XXII–2 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Timed Out!
int TimedInput( ) {signal(SIGALRM, timeout);…alarm(30); /* send SIGALRM in 30 seconds */GetInput(); /* possible long wait for input */alarm(0); /* cancel SIGALRM request */HandleInput();return(0);
nogood:return(1);
}
void timeout( ) {goto nogood; /* not legal but straightforward */
}
CS33 Intro to Computer Systems XXII–3 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Doing It Legally (but Weirdly)sigjmp_buf context;
int TimedInput( ) {signal(SIGALRM, timeout);if (sigsetjmp(context, 1) == 0) {
alarm(30); // cause SIGALRM in 30 secondsGetInput(); // possible long wait for inputalarm(0); // cancel SIGALRM requestHandleInput();return 0;
} elsereturn 1;
}
void timeout() {siglongjmp(context, 1); /* legal but weird */
}
CS33 Intro to Computer Systems XXII–4 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
sigsetjmp/siglongjmp
sigsetjmp
siglongjmp
Stack
TimedInput
CS33 Intro to Computer Systems XXII–5 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Exceptions
• Other languages support exception handling
try {something_a_bit_risky();
} catch(ArithmeticException e) {
deal_with_it(e);
}
• Can we do something like this in C?
CS33 Intro to Computer Systems XXII–6 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Exception Handling in C
void Exception(int sig) {
THROW(sig)}
int computation(int a) {
return a/(a-a);
}
int main() {
signal(SIGFPE, Exception);
signal(SIGSEGV, Exception);TRY {
computation(1);
} CATCH(SIGFPE) {fprintf(stderr,
"SIGFPE\n");
} CATCH(SIGSEGV) {fprintf(stderr,
"SIGSEGV\n");
} END
return 0;}
CS33 Intro to Computer Systems XXII–7 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Exception Handling in C
#define TRY \
{ \
int excp; \if ((excp = \
sigsetjmp(ctx, 1)) == 0)
#define CATCH(a_excp) \else if (excp == a_excp)
#define END }
#define THROW(excp) \
siglongjmp(ctx, excp);
CS33 Intro to Computer Systems XXII–8 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Exception Handling in Csigjmp_buf ctx;
int main() {...
{
int excp;
if ((excp = sigsetjmp(ctx, 1)) == 0) {computation(1);
} else if (excp == SIGFPE) {
fprintf(stderr, "SIGFPE\n");} else if (excp == SIGSEGV) {
fprintf(stderr, "SIGFPE\n");
}
}return 0;
}
void exception(int sig) {siglongjmp(ctx, sig);
}
TRY
CATCH
CATCH
END
THROW
CS33 Intro to Computer Systems XXII–9 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Job Control$ who
– foreground job$ multiprocessProgram
– foreground job^Zstopped$ bg[1] multiprocessProgram &
– multiprocessProgram becomes background job 1$ longRunningProgram &[2]$ fg %1multiprocessProgram
– multiprocessProgram is now the foreground job^C$
CS33 Intro to Computer Systems XXII–10 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Process Groups
• Set of processes sharing the window/keyboard
– sometimes called a job• Foreground process group/job
– currently associated with window/keyboard– receives keyboard-generated signals
• Background process group/job– not currently associated with window/keyboard– doesn’t currently receive keyboard-generated
signals
CS33 Intro to Computer Systems XXII–11 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Keyboard-Generated Signals
• You type ctrl-C• How does the system know which
process(es) to send the signal to?
Window
pid 16pgroup 16
pgroup 16
Shell
CS33 Intro to Computer Systems XXII–12 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Foreground Job
WindowShell
pid 16pgroup 16
pgroup 17
pid 17
pid 23
pid 42
pgroup 17
$ multiprocessProgram^C
CS33 Intro to Computer Systems XXII–13 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Background Job
WindowShell
pid 16pgroup 16
pgroup 16
pid 164
pid 179
pid 196
pgroup 164
$ multiprocessProgram2 &$ ^C
CS33 Intro to Computer Systems XXII–14 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Stopping a Foreground Job
WindowShell
pid 16pgroup 16
pgroup 16
pid 17
pid 23
pid 42
pgroup 17
$ multiprocessProgram^Z[2] stopped$
pgroup 17
CS33 Intro to Computer Systems XXII–15 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Backgrounding a Stopped Job
WindowShell
pid 16pgroup 16
pgroup 16
pid 17
pid 23
pid 42
pgroup 17
$ multiprocessProgram^Z[2] stopped$ $
bg
CS33 Intro to Computer Systems XXII–16 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
pgroup 16
Foregrounding a Job
WindowShell
pid 16pgroup 16
pgroup 17
pid 17
pid 23
pid 42
pgroup 17
$ multiprocessProgram^Z[2] stopped$ bg$ fg %2
CS33 Intro to Computer Systems XXII–17 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Quiz 1
$ long_running_prog1 &$ long_running_prog2^Z[2] stopped$ Which process group receives the
SIGINT signal?a) the one containing the shellb) the one containing
long_running_prog1c) the one containing
long_running_prog2
^C
CS33 Intro to Computer Systems XXII–18 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Creating a Process Group
if (fork() == 0) {
// child
setpgid(0, 0);
/* puts current process into a
new process group whose ID is
the process’s pid.
Children of this process will be in
this process's process group.
*/
...
execv(...);
}
// parent
CS33 Intro to Computer Systems XXII–19 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Setting the Foreground Process Group
tcsetpgrp(fd, pgid);// sets the process group of the// terminal (window) referenced by// file descriptor fd to be pgid
CS33 Intro to Computer Systems XXII–20 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Background Input and Output
• Background process reads from keyboard– the keyboard really should be reserved for
foreground process– background process gets SIGTTIN
» suspends it by default
• Background process writes to display– display also used by foreground process– could be willing to share– background process gets SIGTTOU
» suspends it (by default)» but reasonable to ignore it
CS33 Intro to Computer Systems XXII–21 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Kill: Details
• int kill(pid_t pid, int sig)– if pid > 0, signal sig sent to process pid– if pid == 0, signal sig sent to all processes in the
caller’s process group– if pid == −1, signal sig sent to all processes in the
system for which sender has permission to do so– if pid < −1, signal sig is sent to all processes in
process group −pid
CS33 Intro to Computer Systems XXII–22 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Process Life Cycle
ActiveNon-Existent Zombie
CS33 Intro to Computer Systems XXII–23 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Reaping: Zombie Elimination
• Shell must call waitpid on each child– easy for foreground processes– what about background?
pid_t waitpid(pid_t pid, int *status, int options);
– pid values:< −1 any child process whose process group is |pid|−1 any child process0 any child process whose process group is that of caller> 0 process whose ID is equal to pid
− wait(&status) is equivalent to waitpid(-1, &status, 0)
CS33 Intro to Computer Systems XXII–24 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
(continued)
pid_t waitpid(pid_t pid, int *status, int options);
– options are some combination of the following» WNOHANG
• return immediately if no child has exited (returns 0)» WUNTRACED
• also return if a child has stopped (been suspended)» WCONTINUED
• also return if a child has been continued (resumed)
CS33 Intro to Computer Systems XXII–25 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
When to Call waitpid
• Shell reports status only when it is about to display its prompt
– thus sufficient to check on background jobs just before displaying prompt
CS33 Intro to Computer Systems XXII–26 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
waitpid status
• WIFEXITED(*status): 1 if the process terminated normally and 0 otherwise
• WEXITSTATUS(*status): argument to exit• WIFSIGNALED(*status): 1 if the process was terminated
by a signal and 0 otherwise• WTERMSIG(*status): the signal which terminated the
process if it terminated by a signal• WIFSTOPPED(*status): 1 if the process was stopped by a
signal• WSTOPSIG(*status): the signal which stopped the
process if it was stopped by a signal• WIFCONTINUED(*status): 1 if the process was resumed
by SIGCONT and 0 otherwise
CS33 Intro to Computer Systems XXII–27 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Example (in Shell)int wret, wstatus;
while ((wret = waitpid(-1, &wstatus, WNOHANG|WUNTRACED)) > 0){
// examine all children who’ve terminated or stoppedif (WIFEXITED(wstatus)) {
// terminated normally
...
}if (WIFSIGNALED(wstatus)) {
// terminated by a signal
...}
if (WIFSTOPPED(wstatus)) {
// stopped
...}
}
CS33 Intro to Computer Systems XXII–28 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Process Relationships (1)
Init
Login 1 Login 2 Login 3
cmd cmd cmd cmd cmd
Sub proc. Sub proc.
CS33 Intro to Computer Systems XXII–29 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Process Relationships (2)
Init
Login 1 Login 2 Login 3
cmd cmd cmd cmd cmd
Sub proc. Sub proc.
CS33 Intro to Computer Systems XXII–30 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Process Relationships (3)
Init
Login 1 Login 2 Login 3
cmd cmd cmd cmd cmd
Sub proc. Sub proc.
CS33 Intro to Computer Systems XXII–31 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Signals, Fork, and Exec
// set up signal handlers ...if (fork() == 0) {
// what happens if child gets signal?...signal(SIGINT, SIG_IGN);
signal(SIGFPE, handler);signal(SIGQUIT, SIG_DFL);execv("new prog", argv, NULL);// what happens if SIGINT, SIGFPE,// or SIGQUIT occur?
}
CS33 Intro to Computer Systems XXII–32 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Signals and System Calls
• What happens if a signal occurs while a process is doing a system call?
– deal with it at some safe point in the system-call code
– usually just before the return to user mode» system call completes» signal handler is invoked» user code resumed at return from system call
CS33 Intro to Computer Systems XXII–33 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Signals and Lengthy System Calls
• Some system calls take a long time– large I/O transfer
» multi-megabyte read or write request probably done as a sequence of smaller pieces
– a long wait is required» a read from the keyboard requires waiting for
someone to type something
• If signal arrives in the midst of lengthy system call, handler invoked:
– after current piece is completed– after cancelling wait
CS33 Intro to Computer Systems XXII–34 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Interrupted System Calls
• What if a signal is handled before the system call completes?1) invoke handler, then resume system call
• not clear if system call should be resumedor2) invoke handler, then return from system
call prematurely• if one or more pieces were completed,
return total number of bytes transferred• otherwise return “interrupted” error
CS33 Intro to Computer Systems XXII–35 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Interrupted System Calls: Non-Lengthy Case
while(read(fd, buffer, buf_size) == –1) {if (errno == EINTR) {
/* interrupted system call — try again */continue;
}/* the error is more serious */perror("big trouble");exit(1);
}
CS33 Intro to Computer Systems XXII–36 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Quiz 2
int ret;
char buf[128];
fillbuf(buf);
ret = write(1, buf, 128);
• The value of ret is:a) either -1 or 128b) either -1, 0, or 128c) any integer in the range [-1, 128]
CS33 Intro to Computer Systems XXII–37 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Interrupted System Calls: Lengthy Case
char buf[BSIZE];fillbuf(buf);long remaining = BSIZE;char *bptr = buf;for ( ; ; ) {
long num_xfrd = write(fd,bptr, remaining);
if (num_xfrd == –1) {if (errno == EINTR) {/* interrupted early */continue;
}perror("big trouble");exit(1);
}
if (num_xfrd < remaining) {/* interrupted after the
first step */remaining -= num_xfrd;bptr += num_xfrd;continue;
}/* success! */break;
}
CS33 Intro to Computer Systems XXII–38 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Asynchronous Signals (1)
main( ) {void handler(int);signal(SIGINT, handler);
... /* long-running buggy code */
}
void handler(int sig) {
... /* clean up */exit(1);
}
CS33 Intro to Computer Systems XXII–39 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Asynchronous Signals (2)
computation_state_t state;
main( ) {
void handler(int);
signal(SIGINT, handler);
long_running_procedure( );
}
long_running_procedure( ) {
while (a_long_time) {
update_state(&state);
compute_more( );
}
}
void handler(int sig) {
display(&state);
}
CS33 Intro to Computer Systems XXII–40 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Asynchronous Signals (3)
main( ) {void handler(int);
signal(SIGINT, handler);
... /* complicated program */
myput("important message\n");
... /* more program */
}
void handler(int sig) {
... /* deal with signal */
myput("equally important ""message\n");
}
CS33 Intro to Computer Systems XXII–41 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Asynchronous Signals (4)
char buf[BSIZE];int pos;void myput(char *str) {
int len = strlen(str);for (int i=0; i<len; i++, pos++) {
buf[pos] = str[i];if ((buf[pos] == '\n') || (pos == BSIZE-1)) {
write(1, buf, pos+1);pos = -1;
}}
}
CS33 Intro to Computer Systems XXII–42 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Async-Signal Safety
• Which library functions are safe to use within signal handlers?
– abort– accept– access– aio_error– aio_return– aio_suspend– alarm– bind– cfgetispeed– cfgetospeed– cfsetispeed– cfsetospeed– chdir– chmod– chown– clock_gettime– 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– sigsuspend– sleep– sockatmark– socket– socketpair– stat– symlink– sysconf– tcdrain– tcflow– tcflush– tcgetattr
– tcgetpgrp– tcsendbreak– tcsetattr– tcsetpgrp– time– timer_getoverrun– timer_gettime– timer_settime– times– umask– uname– unlink– utime– wait– waitpid– write
CS33 Intro to Computer Systems XXII–43 Copyright © 2019 Thomas W. Doeppner. All rights reserved.
Quiz 3
Printf is not required to be async-signal safe. Can it be implemented so that it is?
a) no, it’s inherently not async-signal safeb) yes, but it would be so complicated, it’s not donec) yes, it can be easily made async-signal safe