title: Perl IO::Socket/IO::Select - reading from a "ready-to-read" socket
body: <p>This is probably not Perl-specific, but my demo is in Perl.</p>
  
  <p>My master program opens a listening socket, and then forks a child process.  The child's first job is to connect to the master and say HELLO.  Then it continues its initialization, and when it is ready, it sends READY to the master.</p>
  
  <p>The master, after having forked the child, waits for HELLO and then goes about other initialization (forking other children, mainly).  Once it has forked all the children and heard HELLO back from each, it proceeds to wait for all of them to say READY.  </p>
  
  <p>It does this using IO::Select->can_read, and then $socket->getline to retrieve the message.</p>
  
  <p>In short, the parent is failing to receive the READY, even though it's being sent by the child.</p>
  
  <p>Here is a hastily-stripped-down version of my program that demo's the bug (I tried to remove irrelevancies but a few may remain).  I'm still confused by issues like whether message boundaries are preserved, and whether "\n" is needed, and which method to use for reading from a socket.  I really don't want to have to think about assembling message fragments, and I'm hoping IO::Select will spare me that.</p>
  
  <p>The demo only spawns one child, for simplicity.</p>
  
  <pre><code>#!/usr/bin/env perl 
  
  use warnings;
  use strict;
  use Carp;
  use File::Basename;
  use IO::Socket;
  use IO::Select;
  use IO::File;                    # for CONSTANTS
  use Net::hostent;                # for OO version of gethostbyaddr
  use File::Spec qw{rel2abs};      # for getting path to this script
  use POSIX qw{WNOHANG setsid};    # for daemonizing
  
  use 5.010;
  
  my $program    = basename $0;
  my $progpath = File::Spec-&gt;rel2abs(__FILE__);
  my $progdir  = dirname $progpath;
  
  $| = 1;                          # flush STDOUT buffer regularly
  
  # Set up a child-reaping subroutine for SIGCHLD.  Prevent zombies.
  #
  say "setting up sigchld";
  
  $SIG{CHLD} = sub {
      local ( $!, $^E, $@ );
      while ( ( my $kid = waitpid( -1, WNOHANG ) ) &gt; 0 ) {
          say "Reaping child process $kid";
      }
  };
  
  # Open a port for incoming connections
  #
  my $listen_socket = IO::Socket::INET-&gt;new(
      Proto     =&gt; 'tcp',
      LocalPort =&gt; 2000,
      Listen    =&gt; SOMAXCONN,
      Reuse     =&gt; 1
  );
  croak "Can't set up listening socket: $!\n" unless $listen_socket;
  
  my $readers = IO::Select-&gt;new($listen_socket)
      or croak "Can't create the IO::Select read object";
  
  say "Forking";
  
  my $manager_pid;
  if ( !defined( $manager_pid = fork ) ) {
      exit;
  }
  elsif ( 0 == $manager_pid ) {
      #
      # ------------------ BEGIN CHILD CODE HERE -------------------
      say "Child starting";
  
      my ($master_addr, $master_port) = split /:/, 'localhost:2000';
  
      my $master_socket = IO::Socket::INET-&gt;new(
          Proto    =&gt; "tcp",
          PeerAddr =&gt; $master_addr,
          PeerPort =&gt; $master_port,
      ) or die "Cannot connect to $master_addr:$master_port";
  
      say "Child sending HELLO.";
  
      $master_socket-&gt;printflush("HELLO\n");
  
      # Simulate elapsed time spent initializing...
      #
      say "Child sleeping for 1 second, pretending to be initializing ";
  
      sleep 1;
      #
      # Finished initializing.
  
      say "Child sending READY.";
  
      $master_socket-&gt;printflush("READY\n");
      say "Child sleeping indefinitely now.";
  
      sleep;
      exit;
      # ------------------- END CHILD CODE HERE --------------------
  }
  
  # Resume parent code
  
  # The following blocks until we get a connect() from the manager
  
  say "Parent blocking on ready readers";
  
  my @ready = $readers-&gt;can_read;
  
  my $handle;
  
  for $handle (@ready) {
      if ( $handle eq $listen_socket ) {    #connect request?
  
          my $manager_socket = $listen_socket-&gt;accept();
          say "Parent accepting connection.";
  
          # The first message from the manager must be his greeting
          #
          my $greeting = $manager_socket-&gt;getline;
          chomp $greeting;
          say "Parent received $greeting";
  
      }
      else {
          say( $$, "This has to be a bug" );
      }
  }
  
  say "Parent will now wait until child sends a READY message.";
  say "NOTE: if the bug works, Ill never receive the message!!";
  
  ################################################################################
  #
  # Wait until all managers have sent a 'READY' message to indicate they've
  # finished initializing.
  #
  ################################################################################
  
  $readers-&gt;add($handle); # add the newly-established socket to the child
  
  do {
      @ready = $readers-&gt;can_read;
      say "Parent is ignoring a signal." if !@ready;
  
  } until @ready;
  
  # a lot of overkill for demo
  
  for my $socket (@ready) {
      if ( $socket ne $listen_socket ) {
          my $user_input;
          $user_input = $socket-&gt;getline;
          my $bytes = length $user_input;
          if ( $bytes &gt; 0 ) {
              chomp $user_input;
              if ( $user_input eq 'READY' ) {
                  say "Parent got $user_input!";
                  $readers-&gt;remove($socket);
              }
              else {
                  say( $$, "$program RECVS $user_input??" );
              }
          }
          else {
              say( $$, "$program RECVs zero length message? EOF?" );
              $readers-&gt;remove($socket);
          }
      }
      else {
          say( $$, "$program RECVS a connect on the listen socket??" );
      }
  } # end for @ready
  say "Parent is ready to sleep now.";
  </code></pre>