This file contains all typos found in the book UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications by W. Richard Stevens, Prentice Hall, 1999, ISBN 0-13-081081-9.
Page | Description |
---|---|
111 | 4th line from bottom of page: "message queue has been initialized" should be "message queue has not been initialized" (990107). |
202 | In the definitions of the two macros
is_read_lockable and is_write_lockable
the return value from lock_test should be negated, as in
#define is_read_lockable(fd, offset, whence, len) \ !lock_test(fd, F_RDLCK, offset, whence, len)because the region is lockable if lock_test returns 0 (990105). |
209 | 2nd line from bottom of page: "starvation of write locks" should be "starvation of writers" (990105). |
233 | 1st line of item "1." near top of page: "In our first solution (Section 7.2)" should be "In our first solution (Section 7.3)" (990107). |
249 | 1st line on page: "as each consumer thread terminates" should be "as each producer thread terminates" (990107). |
263 | The last line of the description for lines 19-23 ("A file is created ... is turned on.") should be the first line of the description for lines 24-32 (990107). |
339 | In the first two lines of the description for lines 19-31 the two occurrences of "consumer" should be "producer" (990208). |
376 | Line 22 of Figure 15.16: server1 should be serverunref1 (990215). |
378 | Line 23 of Figure 15.17: server1 should be serverunref2 (990215). |
378 | 8th line from bottom of page (continuation line of command): "clientunref2 /tmp/door2 55 &" should be "clientunref2 /tmp/door2 66 &" (990215). |
386 | Fifth line from top of page: replace my_thread with my_create (990215). |
386 | Second line above Server creation procedure: replace "calls my_thread" with "specifies my_thread" (990215). |
387 | Line 27 of Figure 15.23: arg should be "(Door_server_proc *) iptr->di_proc" (990215). |
387 | Line 40 of Figure 15.23: my_thread should be my_create (990215). |
388 | Last line of page: replace my_thread with my_create (990215). |
389 | First line of server output (15 lines from bottom of page): replace my_thread with my_create (990215). |
390 | Second and fourth lines from top of page: replace my_thread with my_create (990215). |
391 | First line on page: replace thread_exit with pthread_exit (990215). |
399 | 8th line from bottom of page: replace "or within threads in different processes" with "or between threads in different processes" (990226). |
400 | First line beneath Figure 16.1: replace "whose name end" with "whose names end" (990226). |
417 | In the 3rd paragaph ("An RPC packet ..."): replace the three occurrences of "picture" with "photo" (990226). In the 5th line of that paragraph, replace "different forms of credentials" with "different forms of verifiers". |
424 | Third line below Premature Termination of Server: replace clnt_call with clnt_create (990409). |
441 | First line of description for lines 20-22: replace "host-to-network" with "network-to-host" (990226). |
531 | Last line on page: replace my_thread with my_create (990215). |
532 | Second line for 16.1: replace "After we terminate out client" with "After we terminate out server" (990226). |
532 | Second line for 16.2: replace "The next reply for" with "The next reply from" (990226). |
550 | Add page 391 to the index entry for pthread_exit (990215). |
557 | Delete the index entry for thread_exit (990215). |
Page | Description |
---|---|
15 | Indented paragraph one-third of the way down the page: change "from this URL" to "from this site" (981120). |
16 | 9th line of Section 1.9: in "each type of IPC as either can be" delete "as either" (981120). |
28 | Item 3 near the bottom of the page: "the low-order 8 bits of the id." should be "the low-order 8 bits of the id (which must not be 0)." (981020). See the Comments to Readers at the end of this file for more details on this correction. |
37 | First line of first example (from /etc/system file): change "4et" to "set" (981216). |
48 | Line 12 of Figure 4.9: in the comment, change "delete" to "ignore" (981125). (Compare this ignoring of the newline to the actual deletion of the newline in the subsequent errata for Figure 4.15 on p. 53.) |
53 | Line 12 of Figure 4.15: replace n--; with buff[n-1] = '\0'; (981125). |
62 | Line 7 of Figure 4.23: change the declaration of buff to buff[MAXLINE+1] (981125). |
62 | Figure 4.23: add exit(0); between lines 45 and 46 (981102). |
65 | 13th line from top of page: "if we invoke the client" should be "if we invoke the server" (981125). |
75 | Last line of 1st paragraph: "for which it having" should be "for which having" (981215). |
82 | 6th line from top of page: "(indicated by an option letter followed by a colon)" is better as "(indicated by a colon following the option letter in the third argument)" (981215). |
95 | 1st line of 2nd indented paragraph: "Two more variants" should be "Two variants" (981215). |
100 | Parenthetical note, about Digital Unix 4.0B: "33 through 38" should be "33 through 48" (980906). |
102 | Description for lines 18-21: add the following sentence
to the end of this paragraph:
"This function also sets the mask of signals to block
while the signal handler is executing." (981020).
See the Comments to Readers at the end of this file for more details on this correction and the following corrections to pages 103-105. |
103 | Figure 5.17: add a third argument,
&newset, in the three calls to the function
Signal_rt on lines 19-21 (981020):
Signal_rt(SIGRTMAX, sig_rt, &newset); Signal_rt(SIGRTMAX - 1, sig_rt, &newset); Signal_rt(SIGRTMAX - 2, sig_rt, &newset); |
104 | Bottom portion of page
showing the Digital Unix 4.0B results (981020):
given the corrections to Figures 5.17 and 5.18,
these results are now correct.
Change this line to
"We now run the program under Digital Unix 4.0B and see the
expected results."
The last nine lines on the page are now:
received signal #46, code = -1, ival = 0 received signal #46, code = -1, ival = 1 received signal #46, code = -1, ival = 2 received signal #47, code = -1, ival = 0 received signal #47, code = -1, ival = 1 received signal #47, code = -1, ival = 2 received signal #48, code = -1, ival = 0 received signal #48, code = -1, ival = 1 received signal #48, code = -1, ival = 2 |
105 | Top four lines of page, change to (981020):
The nine signals are queued and then delivered in the order that we expect: the lowest-numbered-signal first, and for a given signal, the three occurrences are delivered in FIFO order. The Solaris 2.6 implementation appears to have a bug. |
105 | 2nd line of signal_rt Function paragraph: "that provides realtime Posix semantics" should be "that provides reliable Posix semantics" (981215). |
105 | Figure 5.18: a third argument is being added to this function,
a signal set that specifies the set of signals to be blocked
while the signal handler is executing (981020).
Change line 3 to
signal_rt(int signo, Sigfunc_rt *func, sigset_t *mask)and change line 7 to act.sa_mask = *mask; /* signals to block */ |
109 | Last word of 1st line of 2nd paragraph describing lines 26-32: "initial-ized" should be "initial-ized," (981215). |
136 | Figure 6.4, line 16: change second argument to Ftok from 0 to 1 (981020). |
136 | Figure 6.5, line 13: change second argument to Ftok from 0 to 1 (981020). |
137 | Figure 6.6, line 23: change second argument to Ftok from 0 to 1 (981020). |
138 | Figure 6.7, line 8: change second argument to Ftok from 0 to 1 (981020). |
164 | Caption for Figure 7.3: "consumer" should be "consume" and "producer" should be "produce" (981215). |
171 | 2nd line from top: "by the thread calling pthread_cond_wait" should be "by the thread calling pthread_cond_signal" (980910). |
177 | 2nd line in paragraph following indented items 1 and 2: in "as long as no thread is reading or modifying" delete "reading or" (981203). In the next sentence change "modified only if no other thread is reading the data" to "modified only if no other thread is reading or modifying the data". |
186 | Comment on line 14 of Figure 8.8: "releasing a reader" should be "releasing a writer" (981216). |
272 | Figure 10.52, line 29: change second argument to ftok from 0 to 1 (981020). |
274 | Figure 10.53, line 60: change second argument to ftok from 0 to 1 (981020). |
276 | Figure 10.55, line 8: change second argument to ftok from 0 to 1 (981020). |
289 | Figure 11.2, line 17: change second argument to Ftok from 0 to 1 (981020). |
291 | Figure 11.3, line 8: change second argument to Ftok from 0 to 1 (981020). |
291 | Figure 11.4, line 12: change second argument to Ftok from 0 to 1 (981020). |
292 | Figure 11.5, line 12: change second argument to Ftok from 0 to 1 (981020). |
293 | Figure 11.6, line 20: change second argument to Ftok from 0 to 1 (981020). |
295 | Figure 11.7, lines 14 and 20: change second argument to Ftok from 0 to 1 (981020). |
346 | Figure 14.1, line 19: change second argument to Ftok from 0 to 1 (981020). |
347 | Figure 14.2, line 8: change second argument to Ftok from 0 to 1 (981020). |
347 | Figure 14.3, line 10: change second argument to Ftok from 0 to 1 (981020). |
348 | Figure 14.4, line 10: change second argument to Ftok from 0 to 1 (981020). |
355 | 7th line of item 2: remove the extraneous comma (980928). |
507 | Line 71: change "three headers" to "two headers" and remove ", and <sys/sockio.h>" from line 72 (981120). |
512 513 | The strcat on line 78 (p. 513) can write one byte beyond the end of the buffer (980714). One solution is to change line 68 to char buf[MAXLINE + 1]; and then change the two sizeof(buf) (lines 71 and 77) to MAXLINE. This guarantees that the buffer is always terminated by a newline followed by a null byte. |
518 | Solution for Exercise 4.6: in the first line change "(write-only)" to "(read-only)" and in the second line change "(read-only)" to "(write-only)" (981125). |
524 | 2nd line of solution for Exercise 10.2: "exists it, is" should be "exists, it is" (980924). |
527 | Figure D.9, line 20: change second argument to Ftok from 0 to 1 (981020). |
inside back cover: Add a third argument to the prototype for signal_rt, as per the correction shown earlier for page 105 (971020). |
if ( (n = mesg_send(fd, mptr)) != MESGHDRSIZE + mptr->mesg_len)that is, the expected value from the write on line 7.
Page | Comment |
---|---|
28 | Unix 98 now states that the behavior of ftok is unspecified if the low-order 8 bits of the id are 0. Looking around I see the Solaris and Digital Unix man pages now make this same statement. I have no idea when this disclaimer was added, and my 1991 "System V Interface Definition" does not have this statement. AIX even goes so far as to return an error if the id is 0, which IMHO is going just a little too far. Indeed, looking at three different implementations of ftok--System V Release 2, GNU libc, and BSD/OS--not one of these three requires that the id be nonzero: all just logically-OR in the low-order 8 bits of the id regardless of its value. Nevertheless all 19 uses of an id of 0 in the 1st printing will be changed to 1 in the 2nd printing, to avoid problems on systems such as AIX. |
101 | My reason for the second parenthetical remark concerning siginfo_t is that of all the structures defined by Posix.1 (aiocb, group, itimerspec, lock, mq_attr, passwd, sched_param, sigaction, sigevent, siginfo_t, sival, stat, termio, timespec, and utimbuf) only siginfo_t is defined using a typedef. Yes, Posix.1 appends _t to the names of all its primitive system data types (pid_t, pthread_t, etc.) but none of these need be structures and there are no structure member names defined for any of these data types. Therefore, naming siginfo_t, which must be a structure, with the _t suffix struck me as a mistake. The reason for this oddity is probably that siginfo_t was defined by SVR4 (the earliest definition that I can find for it is in the "System V Interface Definition," Third Edition, Aug. 1989) and then ignored by Posix until the P1003.4 realtime extensions. Indeed, p. 354 (the Rationale) of 1003.1b-1993 talks about this name breaking the convention, and the reason listed is to follow existing practice and thus promote portability. |
102 | There was a bug in the test program in Figure 5.17 of the
1st printing. The correction in the 2nd printing is listed
earlier in this errata, for pages 102-105.
The bug illustrates a "feature" of realtime signals
that we must account for.
The correction is to specify a third argument to our signal_rt function (Figure 5.18) that specifies the set of signals to be blocked while the signal handler is executing. In Figure 5.17 this argument is now specified as &newset, which contains all three of the realtime signals that the test program is generating. The underlying problem is that while the signal numbers of the realtime signals (33 through 48 for Digital Unix) specify their priority with regard to delivery when more than one of the realtime signals is pending (in our example, nine signals with numbers 46, 47, and 48 are all pending when all three signal numbers are unblocked, so the lowest numbered signal is delivered first), what determines whether another signal can then be delivered while that signal handling function is executing is the sa_mask of that signal handling function. Therefore, whenever we are dealing with more than one realtime signal, we must specify an sa_mask value for each of the realtime signal's signal handling function, and that mask should block all remaining realtime signals with a higher number (that is, with a lower priority). The rules of Posix (p. 75 of [IEEE 1996]) guarantee that when multiple realtime signals are pending the lowest numbered is delivered first, but it is our responsibility to then guarantee that a lower priority realtime signal does not interrupt our signal handling function; we do that by specifying an sa_mask value for the signal handling function. Since we are now blocking all three of the realtime signals in this example from the signal handling function, calling printf as a simple diagnostic tool is probably OK. But a better technique of printing the order in which the signals are delivered is to change Figure 5.17 as follows: First, allocate two globals: static volatile siginfo_t arrival[10]; static volatile int nsig;Then have the signal handler save its info argument in this array: static void sig_rt(int signo, siginfo_t *info, void *context) { arrival[nsig++] = *info; /* save info for child to print */ }Lastly, have the child print the information in this array before terminating: sleep(3); /* let all queued signals be delivered */ for (i = 0; i < nsig; i++) { printf("received signal #%d, code = %d, ival = %d\n", arrival[i].si_signo, arrival[i].si_code, arrival[i].si_value.sival_int); } exit(0); |
102 | One reader has suggested an alternate solution to the
just-listed problem: retain the 2-argument version of the
signal_rt function on p. 105 but have the function
block all lower priority signals.
To do this, add the following two declarations to the function
sigset_t mask; int s;and then replace line 7 with the following /* compute mask of all lower-priority signals */ Sigemptyset(&mask); for (s = signo + 1; s <= SIGRTMAX; s++) Sigaddset(&mask, s); act.sa_mask = mask; /* block all lower-priority signals */ |
205 | Note that it is easier to initialize the sequence number file to 1 using "echo 1 > seqno". |
205 | Be aware that the loopfcntl program can take much longer to execute if the seqno file is on an NFS mounted filesystem. You should try this if you have access to NFS--it is somewhat an extension to Exercise 9.7. Another interesting measurement is to time the program when the file is on the /tmp filesystem, as many implementations allow this filesystem to be stored in memory. |
209 | You can add the line "wait(NULL); wait(NULL);" between lines 34 and 35 of Figure 9.8 to wait for both children to terminate, if you want to avoid the shell prompt during the children's output. |
211 | Same comment as earlier for page 209. |
312 | You can add the line "wait(NULL);" between lines 34 and 35 of Figure 12.10 to wait for the child to terminate, if you want to avoid the shell prompt during the child's output. |
314 | Same comment as earlier for page 312, between lines 36-37. |
356 | The URL for the Linux implementation of doors has moved to http://www.rampant.org/doors/. |