Writing to a socket and handling broken pipes

Juan Mendes picture Juan Mendes · Aug 26, 2011 · Viewed 17.8k times · Source

I have some code in PHP that connects to a socket. I've been getting a broken pipe intermittently while writing to it. The problems seems to go away if write to the pipe again. I'm wondering what's required (the safest way) to recover from it. I'm also wondering whether socket_write may return without writing the full string that was passed into it. Here's what I have currently.

function getSocket() {
  $socket = socket_create( AF_UNIX, SOCK_STREAM, 0 );
  if ( $socket === FALSE ) {
    throw new Exception(
      "socket_create failed: reason: " . socket_strerror( socket_last_error() ));
    }
  }

  $result = socket_connect($socket, $address);
  if ($result === false) {
    throw new Exception("socket_connect() failed.\nReason: ($result) " .
        socket_strerror(socket_last_error($socket)));
  }
  return $socket;
}

function writeSocket($stmt) {
  $tries = 0;
  $socket = getSocket();
  do {
    // Is is possible that socket_write may not write the full $stmt?
    // Do I need to keep rewriting until it's finished?
    $writeResult = socket_write( $socket, $stmt, strlen( $stmt ) );
    if ($writeResult === FALSE) {
      // Got  a broken pipe, What's the best way to re-establish and 
      // try to write again, do I need to call socket_shutdown?
      socket_close($socket);
      $socket = getSocket();
    }
    $tries++;
  } while ( $tries < MAX_SOCKET_TRIES && $writeResult ===  FALSE);
}

Answer

geocar picture geocar · Aug 27, 2011

Q1. I'm wondering what's required (the safest way) to recover from it.

A: That depends on the application. The socket listener is closing the connection, or you've set socket options that you're not showing us. How you deal with either of these things depends on the semantics of the application.

Q2. I'm also wondering whether socket_write may return without writing the full string that was passed into it.

A: Yes. socket_write() can write no bytes, some of the bytes, or all of the bytes before returning. If it returns a value greater than zero but less than the length of the input, you should adjust offsets (perhaps using substr()). If it returns zero or less, inspect socket_last_error() for clues as to whether it is retry-able. This contortion is covered in the manual.