Perl Cookbook

Errata for Perl Cookbook

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious Technical Mistake Minor Technical Mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted By Date Submitted
Printed Page xxx
2/3 down

s/printer pager/printer paper ... "greatly contributing to global deforestation"

Printed Page Examples
The pcookexamples.tar.gz file on the ftp server When extracting the tar, the file 9781565922433.examples/ch17/nonforker Contains a type on line 89 it reads: {$! == POSIX::EWOULDBLOCK) { it should read: $! == POSIX::EWOULDBLOCK) { (ie there is an extra open-curly-brace at the start of the line)

Printed Page 31
sub parse_csv

some local settings of MS Excel will generate CSV file with semicolon separator rather than comma. for general use of this subroutine I added variables and corrected this code so that it will return the fields "as is". Enclosing characters (double quotes) will also be returned: my $separator = ';'; my $enclosure = '"'; my $escape = '"'; ..... push(@new, $+) while m{ ($enclosure[^$enclosure$escape]*(?:$escape.[^$enclosure$escape]*)*$enclosure)$separator? | ([^$separator]+)$separator? | $separator }gx; push(@new, undef) if substr($_, -1,1) eq $separator; ......

Yannis L.  Jun 26, 2009 
Printed Page 64
last paragraph

The commify subroutine attempts to return a scalar value of the commified text, but perl versions 5.005_03 and v5.6.0 appear to truncate everything from the first comma on, turning 123,456,789 into 123. Also, the attempt to return the reverse of the formatted text seems to fail. My corrected version is as follows: sub commify { my $text = reverse $_[0]; $text =~ s/(ddd)(?=d)(?!d*.)/$1,/g; $text = reverse $text; return $text; } This appears to work without loss in both perl versions mentioned, though the text returned must be formatted and printed as text, not a scalar value. In order to simulate the %9.2f formatting for a scalar value, the commified text was filtered with the following expression: $comm_text =~ s/(.dd).*$/$1/; Then the text can be printed with the '%21s' formatting string.

Printed Page 177
6.8 Solution description Koanstyle

1st paragraph: "The operator ... doesn't return true if both its tests are true on the same line" last paragraph: "The ... operator doesn't test both conditions at once if the first one is true." The resolution happens on p179 2nd paragraph: ".. will not print any further lines." (if both tests are true) "OTOH, ... will continue until the *next* line matches /end/ because it never tries to test both" i.e. There is a condition zero "most_recent_condtion_that_was_true" which is initialized to "theSecond" and the first paragraph is wrong ?

Printed Page 245
1st paragraph of the "Discussion"

"The numbers are normally represented by names like LOCK_EX, which you can get from the Fcntl or IO::File modules." IO::File does not export LOCK_EX, LOCK_SH, LOCK_NB, LOCK_UN by default or when you ask it to. A quick look at IO::File (v1.09) eval { # Make all Fcntl O_XXX constants available for importing require Fcntl; my @O = grep /^O_/, @Fcntl::EXPORT; Fcntl->import(@O); # first we import what we want to export push(@EXPORT, @O); }; shows that that only constants beginning with O_ are exported.

Printed Page 297
1st paragraph

In example 8-5 bgets, the line printing the string doesn't read from the opened filehandle, thus ignoring the seek completely and always reading from offset 0. The line: printf qq{%#x %#o %d "%s" }, $addr, $addr, $addr, scalar <>; Should read: printf qq{%#x %#o %d "%s" }, $addr, $addr, $addr, scalar <FH>;

Printed Page 330
in sub wanted

1 if (-d _) { # then make a real directory 2 mkdir("$dstdir/$name", $mode) 3 or die "can't mkdir $dstdir/$name: $!"; should be if (-d $_) { # then make a real directory unless (-d "$dstdir/$name") { mkdir("$dstdir/$name", $mode) or die "can't mkdir $dstdir/$name: $!"; } the $_ is mangled in line1, and the mkdir will return error, because $dstdir has just been created in the previous for loop ...

Printed Page 542

You promise a recipe to suppress the USER to resize a Perl/Tk window. However, with the given recipe also the PROG won't adapt the window size anymore. Instead of $main->bind('<Configure>' etc etc ), simply use $main->resizable(0,0). The recipe would look trivial then, but would hold the promise: No resizing by user, but no restraint to prog.

Printed Page 591
2nd paragraph

waitpid() should be called with WNOHANG rather than &WNOHANG

Printed Page 617
Code under Discussion

The code for using IO::Socket for a Unix socket does not work. Even after modifying the the most recent Errata: $sock = IO::Socket::UNIX->new( Local => "/tmp/mysock", Type => SOCK_DGRAM, Listen => 5 ) or die $@; Generates a simple died error. Changing the last line to or die $!; gives more detail: Operation not supported on transport endpoint at ./ line 9. Removing the Listen => 5 makes it work. HOWEVER: Using this code snippet, and the client/server UDP code from page 615-616, I can not get a working Unix domain client/serv er to pass a message. The client passes to the server, but the server dies with No such file or directory at ./ line 19. When it tries to send the message back. A full example of working client/servers for the Unix domain would probably be helpfull.

Printed, Safari Books Online Page 624
Solution, 17.11 Forking Server

The REAPER function uses the following loop to prevent zombies: 1 until (-1 == waitpid(-1, WNOHANG)); While this will clean up your dead children, it has the unfortunate property of looping until all current children are complete, since waitpid(-1, WNOHANG) returns 0 if there are any current children. A better solution would be either 1 until( 0 >= waitpid(-1, WNOHANG)); or 1 while (waitpid(-1, WNOHANG) > 0));

Anonymous  Jul 25, 2011 
Printed Page 629
line 10

in example 17-6 nonforker, the use of tie seems to be required for all 3 hashes (%inbuffer, %outbuffer, and %ready), but the example only tied the %ready hash. I think the following 2 statements are missing in the example: tie %inbuffer, 'Tie::RefHash'; tie %outbuffer, 'Tie::RefHash';

Printed Page 635
"Solution" example starting at end of page

The example describes how a signal handler can be used to restart a process using a HUP signal. In the HUP handler routine, phoenix(), the PERL exec() routine is used to start a new executable. Referencing "Programming Perl", 2nd edition (the camel book), page 163, the PERL exec() routine uses the execvp(3) system call to implement its functionality. The execvp() call causes the new process to inherit many of the process attributes from the calling process, including the process signal mask (see sigprocmask(2)). When the phenix() handler is executed, the process has the HUP signal blocked. Therefore, this example works only for the first time that the HUP signal is sent to the process. All subsequent signals have no effect. I have tested the example code, and I found this to be true (using the Solaris psig command to display the signal status). One solution to this problem would be to use the POSIX module to unblock the signal after it is restarted. Unfortunately for me, this example is only similar to my personal coding problem. I encountered this same bug in some PERL code that can be loosely described to work like inetd. In my case, I expected and need exec() to call execl() not execvp(). Any suggestions as to how I can get my PERL code to use execl() would be appreciated.

Printed Page 635
7th paragraph

The solution descriped to 17.16 only seems to catch the first HUP signal, not the following ones. I've tried re-install the HUP handler after it's been called, but still no luck. I've tried the sample code on both FreeBSD and Linux. I checked teh Errata for my edition (August 1998) and found a typo, but nothing relating to the solution. Additionally, I searched on google's usenet search and it seems others have had similar problems.

Safari Books Online 638
Section 16.8, "Solution"

The example given for open2() is: $pid = open2(*README, *WRITEME, $program) ; However, open2() uses this argument order (from the pod documentation): $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'some cmd and args'); In other words, the output file handle comes first, then the input one. The example as given in the book will not work. IMPORTANT NOTE: open3() in IPC::Open3 uses the input, output and error file handles as the first three arguments. In other words, its argument order is different from open2() in IPC::Open2.

Jim Goltz  Mar 10, 2010 
Printed Page 652
3rd program block

$mailer = Mail::Mailer->new("smtp", ""); is an obsolete syntax that does not work with newer Mailer versions. It should now read: $mailer = Mail::Mailer->new("smtp", Server=>"");

Printed Page 716
90 mm down from top of page

Book recommends using module HTML::Parse . This module has been depricated. HTML::Parser is now typically advocated as a having superceded HTML:Parse.

Printed Page 727
20.12 solution

The solution won't work. The regular expression used to split the line has a flaw. of the date-time-timezone part, the closing square bracket ']' is missing: [([^:]+):(d+:d+:d+) ([^]]+) should become [([^:]+):(d+:d+:d+) ([^]]+)]