Re: [PATCH] perlipc.pod Revamp

[email protected] (Shlomi Fish) Sun, 7 Nov 2010 21:23:54 +0200
Newsgroups perl.perl5.porters,perl.documentation
Message-ID <[email protected]>
OK, now replying in detail.

On Monday 01 November 2010 19:49:54 Tom Christiansen wrote:
> Thank you for your edits.  I agree with most of them.
> 
> A lot of these are just personal style things.  It's nearly not worth
> commenting on.  My own style *has* gotten more regular since I wrote that,
> but not much looks too seriously different from how I'd write things today.
> This is mostly quibbling, although there are a few genuine items that
> reauire addressing.
> 
> I haven't read the replies yet.
> 
> >+    our $shucks = 0;
> 
> I'm always nervous about initializing a global through our().
> You should only do so once, but nothing guarantees that you do.
> I'd never such in an example, because it's too fragile.
> 

Well, without this our declaration, the example won't pass "use strict;", so I 
had to add it. Would "my" be better here? "my" should work I think But I 
wasn't sure about it.

> >     sub catch_zap {
> >     
> >         my $signame = shift;
> >
> >+
> >
> >         $shucks++;
> >
> >+
> >
> >         die "Somebody sent me a SIG$signame";
> >     
> >     }
> >
> >+
> >
> >     $SIG{INT} = 'catch_zap';  # could fail in modules
> >     $SIG{INT} = \&catch_zap;  # best strategy
> 
> I don't much mind the vertical whitespace following the function,
> but I see no reason for it within the function.  The more
> vertical whitespace, the more you dilute the code density of what
> can be immediately apprehended at a glance.  Sometimes you want
> to do that, but sometimes you want *not* to do it.
> 
> Remembering that these code snippets need to fit comfortably on a
> manpage, which is a paged document, I suspect that this case
> belongs to the latter group, not to the former.
> 

Very well, I removed it in my copy on github.

> >@@ -45,11 +48,21 @@ system, or you can retrieve them from the Config
> >module. Set up an
> >
> > indexed by name to get the number:
> >     use Config;
> >
> >-    defined $Config{sig_name} || die "No sigs?";
> >-    foreach $name (split(' ', $Config{sig_name})) {
> >-        $signo{$name} = $i;
> >-        $signame[$i] = $name;
> >-        $i++;
> >+
> >+    if (!defined $Config{sig_name})
> >+    {
> 
> See, more spurious vertical whitespace.  If you must make this
> a block, it should be clustered.  And I suspect that boolean
> truth would suffice.

OK, I'll reconsider.

> 
> >+        die "No sigs?";
> >+    }
> >+
> >+    my (%signo, @signame);
> >+
> >+    my $index = 0;
> >+
> >+    foreach my $name (split(' ', $Config{sig_name})) {
> 
> I never write "foreach my" because my brain never inserts the
> English word "of" before the "my"; I always write "for my".

I don't have a problem with that (People say "for each child in my family", 
etc.) and generally the Perl custom is to use foreach for iterating over a 
list, and "for" for either C-style for-loops or iterating over a range.

> 
> >+        $signo{$name} = $index;
> >+        $signame[$index] = $name;
> 
> These days I would work harder to vertically align the equal signs
> between adjacent assignments.

Fixed.

> 
> >+
> 
> More diluting vertical whitespace.
> 
> >+        $index++;
> >
> >     }
> > 
> > So to check whether signal 17 and SIGALRM were the same, do just this:
> >@@ -79,8 +92,9 @@ values are "inherited" by functions called from within
> >that block.)
> >
> >     sub precious {
> >     
> >         local $SIG{INT} = 'IGNORE';
> 
> I'd now write that "IGNORE".  My current *personal* style is to
> use double quotes on all strings I am not trying to have *not*
> interpolate.  I find it easier to read because the glyph is
> wider, so can't ever look like a backquote no matter the font.

Hmmm. Damian's PBP recommends using single-quotes for strings that don't have 
interpolated variables/etc., and double quotes when you need interpolation and 
other features of ""/qq{}.

> >     sub more_functions {
> >     
> >         # interrupts still ignored, for now...
> 
> I might say SIGINTS instead of interrupts, which I
> tend to think of as hardware things.

Fixed in my copy.

> 
> >     }
> >
> >@@ -116,7 +130,7 @@ You may be able to determine the cause of failure
> >using C<%!>.
> >
> > You might also want to employ anonymous functions for simple signal
> >
> > handlers:
> >-    $SIG{INT} = sub { die "\nOutta here!\n" };
> >+    $SIG{INT} = sub { die "\nOutta here!\n"; };
> 
> Oh, no.  I would no more put a semicolon at the end of a statement whose
> close brace immediately follows on the same line than I would put a comma
> after the last list element right before a close paren on the same line,
> and for just the same reason.
> 
> I would also not never omit them if the closing punctuation is on
> a separate line.

Well, this is bikeshedding. I think always adding a semicolon at the end of 
every statement is good style, and is safer if you add stuff later on. PBP 
recommends it, I believe.

> >+
> >
> >         cleanup_child($pid, $?);
> >     
> >     };
> 
> That's a great deal of vertical whitespace.  I can't see what
> it usefully adds.  It looks like double-spaced text.
> 

Removed to make the example shorter.

> >+
> >+            $children{$pid}=1;
> >
> >             # ...
> >             system($command);
> >             # ...
> >
> >+
> 
> Why the vertical whitespace here?  Why swap the other
> "# ..."  with a blank line, but not these?
> 

I swapped it with the comment "I'm the child - do something".

> >        }
> >     
> >     }
> >
> >@@ -199,12 +226,16 @@ using longjmp() or throw() in other languages.
> >
> > Here's an example:
> >     eval {
> >
> >-        local $SIG{ALRM} = sub { die "alarm clock restart" };
> >+
> >+        local $SIG{ALRM} = sub { die "alarm clock restart"; };
> 
> No new semicolon.
> 

OK, who gets to veto this? 

> > If the operation being timed out is system() or qx(), this technique
> > is liable to generate zombies.    If this matters to you, you'll
> >
> >@@ -246,16 +277,18 @@ info to show that it works and should be replaced
> >with the real code.
> >
> >   $|=1;
> 
> Spaces around the equals sign.
> 
Done.

> >       my $c = 0;
> >       while (++$c) {
> >           sleep 2;
> >           print "$c\n";
> 
> I'm not proud of having used a signal letter for a variable name.
> In fact, I don't care for it here.

Changed to $count.

I integrated all your commentary into:

[code]
    sub _create_named_pipe
    {
        local $ENV{PATH} = $ENV{PATH}
            . join "", map { ":$_" } qw(/etc /usr/etc /sbin/ /usr/sbin);

        if (system('mknod', $path, 'p') != 0) {
            if (system('mkfifo', $path) != 0) {
                die "mk{nod,fifo} $path failed - $?";
            }
        }

        # Return success.
        return 1;
    }
[/code]

The brace on a separate line is my own personal style and does not belong in 
perl*.pod.

> >+            }
> >+        }
> >+
> >+        # Return success.
> >+        return 1;
> >
> >     }
> >
> >@@ -313,22 +357,26 @@ from that file, the reading program will block and
> >your program will
> >
> > supply the new signature.  We'll use the pipe-checking file test B<-p>
> > to find out whether anyone (or anything) has accidentally removed our
> > fifo.
> >
> >-    chdir; # go home
> >-    $FIFO = '.signature';
> >+    use POSIX qw();
> >+
> >+    chdir; # Go home
> >+    my $fifo_filename = '.signature';
> >
> >     while (1) {
> >
> >-        unless (-p $FIFO) {
> >-            unlink $FIFO;
> >-            require POSIX;
> >-            POSIX::mkfifo($FIFO, 0700)
> >-                or die "can't mkfifo $FIFO: $!";
> 
> The goal was not to load the POSIX module unconditionally.
> That has been lost.
>

Why should we not load POSIX always? Is this a micro-optimisation?

> >-        print FIFO "John Smith (smith\@host.org)\n", `fortune -s`;
> >-        close FIFO;
> >-        sleep 2;    # to avoid dup signals
> >+        # Next line blocks until there's a reader.
> >+        open (my $fifo_fh, ">", $fifo_filename)
> >+            or die "can't write ${fifo_filename}: $!";
> >+        print {$fifo_fh} "John Smith (smith\@host.org)\n", `fortune -s`;
> 
> Why in the world has that become a dative block?
> 

PBP recommends (and I agree) against writing

print $fifo_fh "Hello\n";

Because it is too easy to confuse with:

print $fifo_fh, "Hello\n";

And recommends writing:

print {$fifo_fh} "Hello\n";

instead.

> >+        close $fifo_fh;
> 
> That should test its return value.
> 
> 	close($fifo_fh)	    || die "can't close $fifo_fh:

That would interpolate $fifo_fh there.

I changed it to:

close($fifo_fh) or die "can't close \$fifo_fh: $?";

> >+
> >+        sleep 2;    # To avoid duplicate signals
> 
> Wish I knew what I had been thinking.
>

Should I just remove it?
 
> >-N.B. If a signal of any given type fires multiple times during an opcode
> >+N.B.: if a signal of any given type fires multiple times during an opcode
> 
> I'd try to find something less Latinate.  Plus the style guide says not
> to start sentence with "note that", anyway.
> 

Changed to "One should note that"

> > (such as from a fine-grained timer), the handler for that signal will
> > only be called once after the opcode completes, and all the other
> > instances will be discarded.  Furthermore, if your system's signal queue
> >
> >@@ -397,7 +445,7 @@ breaks into IO operations like C<read> (used to
> >implement Perls
> >
> > E<lt>E<gt> operator). On older Perls the handler was called
> 
> I'd write that as C<< <> >> now.

Done, thanks.

> 
> > immediately (and as C<read> is not "unsafe" this worked well). With
> > the "deferred" scheme the handler is not called immediately, and if
> >
> >-Perl is using system's C<stdio> library that library may re-start the
> >+Perl is using the system's C<stdio> library, that library may re-start
> >the
> 
> I don't thikn I'd hyphenate restart.
> 

Hyphen removed.

> > =back
> >
> >@@ -470,24 +519,27 @@ C<"unsafe"> (a new feature since Perl 5.8.1).
> >
> > Perl's basic open() statement can also be used for unidirectional
> 
> It's not a statement.  It's a function.

Changed.

> 
> > interprocess communication by either appending or prepending a pipe
> >
> >-symbol to the second argument to open().  Here's how to start
> >-something up in a child process you intend to write to:
> >+symbol to the second argument to open(), or by using the three-args form
> >+with the C<"|-"> or C<"-|"> modes (which won't work on Windows systems.)
> >+. Here's how to start something up in a child process you intend to write
> >to:
> >
> >-    open(SPOOLER, "| cat -v | lpr -h 2>/dev/null")
> >-                    || die "can't fork: $!";
> >+    open (my $spooler, "| cat -v | lpr -h 2>/dev/null")
> >+                    or die "can't fork: $!";
> 
> That's unnecessary.

What is and why?

> >+    close ($spooler) or die "bad spool: $! $?";
> 
> That should be
> 
>     close($spooler)	 || die "close to spooler pipe failed: $? $!";
> 
> But that's still awkward.



> 
> > And here's how to start up a child process you intend to read from:
> >-    open(STATUS, "netstat -an 2>&1 |")
> >-                    || die "can't fork: $!";
> >-    while (<STATUS>) {
> >+    open (my $status, "netstat -an 2>&1 |")
> >+                    or die "can't fork: $!";
> 
> Please don't make it all look like the same stuff.  The "||"
> is used for a reason.

Why do you find it preferable over "or"? "or" has an ultra-low precendance and 
so is harder to misuse.

> 
> >+
> >+    while (<$status>) {
> >
> >         next if /^(tcp|udp)/;
> >         print;
> >     
> >     }
> >
> >-    close STATUS || die "bad netstat: $! $?";
> 
> That's actually a bad thing.  Looks like a perl4 vestige.
> 
> >+
> >+    close ($status) or die "bad netstat: $! $?";
> 
> No space.
> 
>     close($status) 	 || die "bad netstat: $! $?";
> 
> All the || should line up to the same column in that example.
> That's why it's strangely indented earlier.
> 

More bikeshedding.

> > =head2 Filehandles
> >
> >@@ -546,7 +598,8 @@ child process cannot outlive the parent.
> >
> > =head2 Background Processes
> >
> >-You can run a command in the background with:
> >+Assuming your shell supports that, you can run a command in the
> >background
> >
> >+with:
> >     system("cmd &");
> >
> >@@ -569,8 +622,8 @@ output doesn't wind up on the user's terminal).
> >
> >     sub daemonize {
> >     
> >         chdir '/'                      or die "Can't chdir to /: $!";
> >
> >-        open STDIN, '/dev/null'        or die "Can't read /dev/null: $!";
> >-        open STDOUT, '>/dev/null'
> >+        open STDIN, '<', '/dev/null'        or die "Can't read /dev/null:
> >$!";
> 
> Nope.  Make all the || die align.  AND DO NOT OMIT THE PARENS AROUND
> THE FUNCTIon CALL!!

Fixed the alignment. There were no parentheses around open.


> >+        close($kid_to_write) or warn "kid exited $?";
> 
> No "or".  I absolutely never ever use it.  That way I never
> get confused as the recent CPAN bug report shows that people do.

Which bug report?

> 
> >     } else {     # child
> >     
> >         ($EUID, $EGID) = ($UID, $GID); # suid progs only
> >
> >-        open (FILE, "> /safe/file")
> >-            || die "can't open /safe/file: $!";
> >+        open (my $file, ">", "/safe/file")
> 
> Why?  There is 100.00000000000% chance that that will behave.
> It's a constant string of known content.

Still, we should not encourage such potentially bad idioms. Here it is 
harmless, but people can learn that it's OK to do ">$myfile" too.

> >     # add error processing as above
> >
> >-    $pid = open(KID_TO_READ, "-|");
> >+    $pid = open($kid_to_read, "-|");
> 
> Since we're getting our knickers in a snit now,
> I wonder where that was declared?

It wasn't - thanks for spotting it. Fixed now.


> >+        # NOT REACHED
> >
> >     }
> > 
> > And here's a safe pipe open for writing:
> >     # add error processing as above
> >
> >-    $pid = open(KID_TO_WRITE, "|-");
> >+    $pid = open($kid_to_write, "|-");
> >
> >     $SIG{PIPE} = sub { die "whoops, $program pipe broke" };
> >     
> >     if ($pid) {  # parent
> >     
> >         for (@data) {
> >
> >-            print KID_TO_WRITE;
> >+            print $kid_to_write;
> 
> And *HERE* is where we have a problem, Houston.  That is
> now incorrect!! This is the price of political correctness
> gone MAD!
> 
>     % perl -le '$fh = \*STDOUT; print $fh'
>     GLOB(0x7e0e6020)
> 
> SEE???  That's why you use handles that Perl knows are handles.
> 

Fixed.
> >     defined $pid or die "fork failed; $!";
> 
> Bad demicolon.  And other things.
> 
>     die "fork failed: $!"  unless defined $pid;
> 
> >     if ($pid) {
> >     
> >         if (my $sub_pid = fork()) {
> >
> >-            close WRITER;
> >+            close $writer;
> 
>     close($writer) || die ....
> 

Fixed.

> >-In the above, the true parent does not want to write to the WRITER
> 
> In the above *what*?  In the code above, I bet.
> 

Fixed.

> >     if ($pid) {
> >
> >-        close READER;
> >+        close $reader;
> >
> >         if (my $sub_pid = fork()) {
> >
> >-            close WRITER;
> >+            close $writer;
> >
> >         }
> >         else {
> >
> >-            # write to WRITER...
> >+            # write to $writer...
> >
> >             exit;
> >         
> >         }
> >
> >-        # write to WRITER...
> >+        # write to $writer...
> >
> >     }
> >     else {
> >
> >-        open STDIN, "<&READER";
> >-        close WRITER;
> >+        open STDIN, "<&", $reader;
> >+        close $writer;
> >
> >         # do something...
> >         exit;
> >     
> >     }
> >
> >@@ -733,11 +787,11 @@ open() which sets one file descriptor to another, as
> >
> >below:
> > Since Perl 5.8.0, you can also use the list form of C<open> for pipes :
> > the syntax
> >
> >-    open KID_PS, "-|", "ps", "aux" or die $!;
> >+    open my $kid_ps, "-|", "ps", "aux" or die $!;
> 
> That looks just terrible I'm sure I would never have
> written such a nasty thing.
> 
>     open(my $kid_ps, "-|", qw[ ps aux ])
> 
> 	|| die "pipe from ps failed: $!";

Corrected.

 > 


> > forks the ps(1) command (without spawning a shell, as there are more than
> > three arguments to open()), and reads its standard output via the
> >
> >-C<KID_PS> filehandle.  The corresponding syntax to write to command
> >+C<$kid_ps> filehandle.  The corresponding syntax to write to command
> >
> > pipes (with C<"|-"> in place of C<"-|">) is also implemented.
> > 
> > Note that these operations are full Unix forks, which means they may not
> > be
> >
> >@@ -775,7 +829,7 @@ While this works reasonably well for unidirectional
> >communication, what
> >
> > about bidirectional communication?  The obvious thing you'd like to do
> >
> > doesn't actually work:
> >-    open(PROG_FOR_READING_AND_WRITING, "| some program |")
> >+    open (my $prog_for_reading_and_writing, "| some program |")
> >
> > and if you forget to use the C<use warnings> pragma or the B<-w> flag,
> >
> > then you'll miss out entirely on the diagnostic message:
> >@@ -813,27 +867,32 @@ commands are designed to operate over pipes, so this
> >seldom works
> >
> > unless you yourself wrote the program on the other end of the
> > double-ended pipe.
> >
> >-A solution to this is the nonstandard F<Comm.pl> library.  It uses
> >-pseudo-ttys to make your program behave more reasonably:
> >+A solution to this is the non-core IPC-Run CPAN distribution (
> >+L<http://search.cpan.org/dist/IPC-Run/> )
> 
> How come that's not written as an IPC::Run module?
> 

What do you mean?

> >+
> >+    use IPC::Run qw(run timeout);
> >+
> >+    my ($in, $out, $err);
> >+    run ['cat', '-n'], \$in, \$out, \$err, timeout(10)
> >+        or die "Cannot run cat: $?";
> 
> That's just terrible.  Use this:
> 
>     run([qw(cat -n)], \($in, $out, $err), timeout(10))
> 
>     	|| die "couldn't run cat -n program: $?";
> 
> Better yet, use an array so you don't have the same
> info in two places:
> 
>     @cat_args = qw[cat -n];
> 
>     run(\(@cat_args, $in, $out, $err) => timeout(10))
> 
>     	|| die "couldn't run @cat_args program: $?";

Fixed to an extent.

> >
> >-    require 'Comm.pl';
> >-    $ph = open_proc('cat -n');
> >
> >     for (1..10) {
> 
> Spaces around operators.

Fixed.

> >also
> >+addresses this kind of thing, but for Unix systems only. This module
> >requires +two other modules from CPAN: IO::Pty and IO::Stty. It sets up a
> >+pseudo-terminal to interact with programs that insist on using talking to
> 
> Don't think that needs hyphenation.
> 
> Don't think using belongs there.
> 

Fixed the using. I think that pseduoterminal looks weird.

> >+the terminal device driver.  If your system is amongst those supported,
> >this
> 
> In my own speech, I more often use "among" when the following
> word begins with a consonant sound.  I'd probably say "amongst
> others" but "among those".  That's a tad precious, perhaps even
> silly: too much like "my nose and mine eyes".
> 

Fixed to among.

> >+may be your best bet.
> >
> > =head2 Bidirectional Communication with Yourself
> >
> >@@ -1095,7 +1154,7 @@ go back to service a new client.
> >
> >         if (! defined($pid = fork)) {
> >         
> >             logmsg "cannot fork: $!";
> >             return;
> >
> >-        }
> >+        }
> >
> >         elsif ($pid) {
> >         
> >             logmsg "begat $pid";
> >             return; # I'm the parent
> >
> >@@ -1125,7 +1184,7 @@ to be reported.  However the introduction of safe
> >signals (see
> >
> > L</Deferred Signals (Safe Signals)> above) in Perl 5.7.3 means that
> > accept() may also be interrupted when the process receives a signal.
> > This typically happens when one of the forked sub-processes exits and
> 
> Don't think that needs hyphenation.
> 

I think it does. Not fixed yet.

Regards,

	Shlomi Fish

-- 
-----------------------------------------------------------------
Shlomi Fish       http://www.shlomifish.org/
Why I Love Perl - http://shlom.in/joy-of-perl

<rindolf> She's a hot chick. But she smokes.
<go|dfish> She can smoke as long as she's smokin'.

Please reply to list if it's a mailing list post - http://shlom.in/reply .