Recitation Signaling 15213 S 04 Recitation Section A

  • Slides: 35
Download presentation
Recitation: Signaling 15213 -S 04, Recitation, Section A l. Debug Multiple Processes using GDB

Recitation: Signaling 15213 -S 04, Recitation, Section A l. Debug Multiple Processes using GDB l. Dup 2 l. Signaling l. L 5 Due: This Wednesday

Debug Multiple Proc’s Using GDB l attach pid n pid: the process id of

Debug Multiple Proc’s Using GDB l attach pid n pid: the process id of a running process l set follow_fork_mode <parent | child> n n – 2– only work in HP-UX and GNU/Linux (kernel >= 2. 5. 60) Fish machines: Linux with kernel 2. 2. 20 15 -213, S’ 04

Attach to a Running Process 1. Run the parent code and create the process

Attach to a Running Process 1. Run the parent code and create the process tsh l l Directly in the shell In GDB 2. Get the pid l $ ps [-e | axu] | grep tsh 3. Run gdb l $ gdb tsh <pid> 4. Attach to the process l – 3– (gdb) attach <pid> 15 -213, S’ 04

Really that Easy? l The process must be started outside GDB n If you

Really that Easy? l The process must be started outside GDB n If you want to debug both the parent process and the child process, you need start another gdb (in another xterm) l You have to type in the gdb & attach commands fast enough --- before the process actually finishes n n You have to modify the source code to let it wait Two methods l sleep(10); l int gdbf = 0; while (!gdbf); l For Lab 5, it is more troublesome n – 4– sdriver runtrace tsh/tshref mycat Demo! 15 -213, S’ 04

Attach to a Running Process 1. Run runtrace and create the process tsh l

Attach to a Running Process 1. Run runtrace and create the process tsh l l Directly in the shell In GDB 2. Get the pid l $ ps [-e | axu] | grep tsh 3. Run gdb l $ gdb tsh <pid> 4. Attach to the process l – 5– (gdb) attach <pid> 15 -213, S’ 04

Dup 2() l Basic concepts on file handler n File descriptor, file table, v-node

Dup 2() l Basic concepts on file handler n File descriptor, file table, v-node table l File sharing --- dup 2() l Practice problems – 6– 15 -213, S’ 04

How the Unix Kernel Represents Open Files Two descriptors referencing two distinct open disk

How the Unix Kernel Represents Open Files Two descriptors referencing two distinct open disk files. Descriptor 1 (stdout) points to terminal, and descriptor 4 points to open disk file. Descriptor table [one table per process] Open file table [shared by all processes] v-node table [shared by all processes] File A (terminal) File pos refcnt=1 File B (disk) File pos refcnt=1 Info in stat struct File access File size File type. . . – 7– File access File size File type. . . stdin fd 0 stdout fd 1 stderr fd 2 fd 3 fd 4 15 -213, S’ 04

How Processes Share Files A child process inherits parent’s open files. Here is the

How Processes Share Files A child process inherits parent’s open files. Here is the situation immediately after a fork Descriptor tables Open file table (shared by all processes) Parent's table File A File pos refcnt=2 File access File size File type. . . – 8– File B . . . fd 0 fd 1 fd 2 fd 3 fd 4 refcnt=2 File access File size File type. . . Child's table File pos. . . fd 0 fd 1 fd 2 fd 3 fd 4 v-node table (shared by all processes) 15 -213, S’ 04

File Sharing Two distinct descriptors sharing the same disk file through two distinct open

File Sharing Two distinct descriptors sharing the same disk file through two distinct open file table entries n E. g. , Calling open twice with the same filename argument Descriptor table (one table per process) Open file table (shared by all processes) v-node table (shared by all processes) File A refcnt=1 File access File size File type . . . fd 0 fd 1 fd 2 fd 3 fd 4 File pos File B File pos refcnt=1 . . . – 9– 15 -213, S’ 04

I/O Redirection dup 2(oldfd, newfd) n Copies (per-process) descriptor table entry oldfd to entry

I/O Redirection dup 2(oldfd, newfd) n Copies (per-process) descriptor table entry oldfd to entry newfd Descriptor table before dup 2(4, 1) fd 0 fd 1 fd 0 a fd 1 fd 2 fd 3 fd 4 – 10 – Descriptor table after dup 2(4, 1) b fd 4 b b 15 -213, S’ 04

I/O Redirection Example Before calling dup 2(4, 1), stdout (descriptor 1) points to a

I/O Redirection Example Before calling dup 2(4, 1), stdout (descriptor 1) points to a terminal and descriptor 4 points to an open disk file. Descriptor table (one table per process) Open file table (shared by all processes) v-node table (shared by all processes) File A File pos refcnt=1 File B File pos refcnt=1 File access File size File type. . . – 11 – File access File size File type. . . stdin fd 0 stdout fd 1 stderr fd 2 fd 3 fd 4 15 -213, S’ 04

I/O Redirection Example (cont) After calling dup 2(4, 1), stdout is now redirected to

I/O Redirection Example (cont) After calling dup 2(4, 1), stdout is now redirected to the disk file pointed at by descriptor 4. Descriptor table (one table per process) Open file table (shared by all processes) v-node table (shared by all processes) File A File pos refcnt=0 File B File pos refcnt=2 File access File size File type. . . – 12 – File access File size File type. . . fd 0 fd 1 fd 2 fd 3 fd 4 15 -213, S’ 04

File Sharing Descriptor table n n Each process has its own Child inherits from

File Sharing Descriptor table n n Each process has its own Child inherits from parents File Table n n set of all open files Shared by all processes Reference count of number of file descriptors pointing to each entry File position V-node table n n – 13 – Contains information in the stat structure Shared by all processes 15 -213, S’ 04

Problem 11. 2 Suppose that foobar. txt consists of the 6 ASCII characters "foobar".

Problem 11. 2 Suppose that foobar. txt consists of the 6 ASCII characters "foobar". Then what is the output of the following program? #include "csapp. h" int main() { int fd 1, fd 2; char c; fd 1 = Open("foobar. txt", O_RDONLY, 0); fd 2 = Open("foobar. txt", O_RDONLY, 0); Read(fd 1, &c, 1); Read(fd 2, &c, 1); printf("c = %cn", c); exit(0); } – 14 – 15 -213, S’ 04

Answer to 11. 2 The descriptors fd 1 and fd 2 each have their

Answer to 11. 2 The descriptors fd 1 and fd 2 each have their own open file table entry, so each descriptor has its own file position for foobar. txt. Thus, the read from fd 2 reads the first byte of foobar. txt, and the output is c = f and not c = o as you might have thought initially. – 15 -213, S’ 04

Problem 11. 3 As before, suppose foobar. txt consists of 6 ASCII characters "foobar".

Problem 11. 3 As before, suppose foobar. txt consists of 6 ASCII characters "foobar". Then what is the output of the following program? #include "csapp. h" int main() { int fd; char c; fd = Open("foobar. txt", O_RDONLY, 0); if(Fork() == 0) {Read(fd, &c, 1); exit(0); } Wait(NULL); Read(fd, &c, 1); printf("c = %cn", c); exit(0); } – 16 – 15 -213, S’ 04

Answer to 11. 3 Child inherit’s the parent’s descriptor table. So child and parent

Answer to 11. 3 Child inherit’s the parent’s descriptor table. So child and parent share an open file table entry (refcount = 2). Hence they share a file position. c = o – 17 – 15 -213, S’ 04

Problem 11. 4 How would you use dup 2 to redirect standard input to

Problem 11. 4 How would you use dup 2 to redirect standard input to descriptor 5? int dup 2(int oldfd, int newfd); n – 18 – copies descriptor table entry oldfd to descriptor table entry newfd 15 -213, S’ 04

Answer to 11. 4 dup 2(5, 0); or dup 2(5, STDIN_FILENO); – 19 –

Answer to 11. 4 dup 2(5, 0); or dup 2(5, STDIN_FILENO); – 19 – 15 -213, S’ 04

Problem 11. 5 Assuming that foobar. txt consists of 6 ASCII characters “foobar”. Then

Problem 11. 5 Assuming that foobar. txt consists of 6 ASCII characters “foobar”. Then what is the output of the following program? #include "csapp. h" int main() { int fd 1, fd 2; char c; fd 1 = Open("foobar. txt", O_RDONLY, 0); fd 2 = Open("foobar. txt", O_RDONLY, 0); Read(fd 2, &c, 1); Dup 2(fd 2, fd 1); Read(fd 1, &c, 1); printf("c = %cn", c); exit(0); } – 20 – 15 -213, S’ 04

Answer to 11. 5 We are redirecting fd 1 to fd 2. (fd 1

Answer to 11. 5 We are redirecting fd 1 to fd 2. (fd 1 now points to the same open file table entry as fd 2). So the second Read uses the file position offset of fd 2. c = o – 21 – 15 -213, S’ 04

Signaling l Busy wait l waitpid() l Racing hazard – 22 – 15 -213,

Signaling l Busy wait l waitpid() l Racing hazard – 22 – 15 -213, S’ 04

Busy Wait if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){

Busy Wait if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ /* do nothing */ } } – 23 – 15 -213, S’ 04

Pause if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ pause();

Pause if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ pause(); } } If signal handled before call to pause, then pause will not return when foreground process sends SIGCHLD – 24 – 15 -213, S’ 04

Sleep if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ sleep(1);

Sleep if(fork() != 0) { /* parent */ addjob(…); while(fg process still alive){ sleep(1); } } – 25 – 15 -213, S’ 04

waitpid () pid_t waitpid(pid_t pid, int *status, int options) n pid: wait until child

waitpid () pid_t waitpid(pid_t pid, int *status, int options) n pid: wait until child process with pid has terminated l -1: wait for any child process n n status: tells why child terminated options: l WNOHANG: return immediately if no children zombied » returns -1 l WUNTRACED: report status of stopped children too – 26 – 15 -213, S’ 04

Status in Waitpid int status; waitpid(pid, &status, NULL); Macros to evaluate status: n n

Status in Waitpid int status; waitpid(pid, &status, NULL); Macros to evaluate status: n n n WIFSIGNALED(status): child exited because of a signal not caught n WTERMSIG(status): gives the terminating signal number n WIFSTOPPED(status): child is currently stopped WSTOPSIG(status): gives the stop signal number n – 27 – WIFEXITED(status): child exited normally WEXITSTATUS(status): return code when child exits 15 -213, S’ 04

Race Hazard l A data structure is shared by two pieces of code that

Race Hazard l A data structure is shared by two pieces of code that can run concurrently l Different behaviors of program depending upon how the schedule interleaves the execution of code. – 28 – 15 -213, S’ 04

eval & sigchld_handler Race Hazard sigchld_handler() { pid = waitpid(…); deletejob(pid); } eval() {

eval & sigchld_handler Race Hazard sigchld_handler() { pid = waitpid(…); deletejob(pid); } eval() { pid = fork(); if(pid == 0) { /* child */ execve(…); } /* parent */ /* signal handler might run BEFORE addjob() */ addjob(…); } – 29 – 15 -213, S’ 04

An OK Schedule time Shell Signal Handler Child fork() addjob() execve() exit() sigchld_handler() deletejobs()

An OK Schedule time Shell Signal Handler Child fork() addjob() execve() exit() sigchld_handler() deletejobs() – 30 – 15 -213, S’ 04

A Problematic Schedule time Shell Signal Handler Child fork() execve() exit() sigchld_handler() deletejobs() addjob()

A Problematic Schedule time Shell Signal Handler Child fork() execve() exit() sigchld_handler() deletejobs() addjob() Job added to job list after the signal handler tried to delete it! – 31 – 15 -213, S’ 04

Blocking Signals sigchld_handler() { pid = waitpid(…); deletejob(pid); } More details 8. 5. 6

Blocking Signals sigchld_handler() { pid = waitpid(…); deletejob(pid); } More details 8. 5. 6 (page 633) eval() { sigprocmask(SIG_BLOCK, …) pid = fork(); if(pid == 0) { /* child */ sigprocmask(SIG_UNBLOCK, …) execve(…); } /* parent */ /* signal handler might run BEFORE addjob() */ addjob(…); sigprocmask(SIG_UNBLOCK, …) } – 32 – 15 -213, S’ 04

Blocking Signals x sigprocmask(SIG_BLOCK, (sigset_t *)SIGCHLD, NULL); sigprocmask(SIG_BLOCK, (sigset_t *)SIGINT, NULL); sigprocmask(SIG_BLOCK, (sigset_t *)SIGTSTP,

Blocking Signals x sigprocmask(SIG_BLOCK, (sigset_t *)SIGCHLD, NULL); sigprocmask(SIG_BLOCK, (sigset_t *)SIGINT, NULL); sigprocmask(SIG_BLOCK, (sigset_t *)SIGTSTP, NULL); sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGTSTP); sigprocmask(SIG_BLOCK, &mask, NULL); – 33 – 15 -213, S’ 04

Blocking Signals if (sigemptyset(&mask) < 0) unix_error("sigemptyset error"); if (sigaddset(&mask, SIGCHLD)) unix_error("sigaddset error"); if

Blocking Signals if (sigemptyset(&mask) < 0) unix_error("sigemptyset error"); if (sigaddset(&mask, SIGCHLD)) unix_error("sigaddset error"); if (sigaddset(&mask, SIGINT)) unix_error("sigaddset error"); if (sigaddset(&mask, SIGTSTP)) unix_error("sigaddset error"); if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) unix_error("sigprocmask error"); – 34 – 15 -213, S’ 04

Summary l Debug Multiple Processes using GDB l Dup 2 l Signaling – 35

Summary l Debug Multiple Processes using GDB l Dup 2 l Signaling – 35 – 15 -213, S’ 04