HansB has asked for the wisdom of the Perl Monks concerning the following question:

This is a Perl, Linux, pipes, network socket question...

I have a simple server using IO::Socket, which is supposed to send one directional data to a client when they connect.

It looks like something like this...

while ( my $client = $server->accept() ) { open( IN, "/usr/bin/someprogram |" ); while ( <IN> ) { if ( $client->connected ) { print $client <IN>; } } }
I did some debugging and it seems to die on the "print $client <IN>" line, so I added "$client->connected", and that helped the issue a little. The server now dies only on the 3rd or 4th time a client disconnects. There are no errors or warnings thrown.

The server sends data fairly rapidly, so I suspect that if the connection is closed after the "$client->connected" is performed but before the print command, it dies?

Replies are listed 'Best First'.
Re: program dies when printing to closed socket, I think
by jbert (Priest) on Aug 16, 2007 at 16:16 UTC
    Yes, by default writing to a closed socket will cause your program to receive a SIGPIPE, which by default will kill it. (See 'man 2 write', search for EPIPE).

    You can ignore or handle the signal (see %SIG in perldoc perlvar), in which case you'll get an error returned from the write and $! will be set to EPIPE (in a numeric context, or the error string in a string context).

    Linux is giving you some default error handling (killing your process via SIGPIPE), if you want something more complex you'll need to check for and handle errors as above. Good luck.

      Thanks! I wrote a quick catcher for SIGPIPE and it's handling client disconnects just fine now.
Re: program dies when printing to closed socket, I think
by almut (Canon) on Aug 16, 2007 at 16:02 UTC

    One first thing to note is that the <IN> in print $client <IN>; is executing in list context, which means you'll only ever call the $client->connected once, before you're sending the entire content to the client...

    Writing the content line-wise might improve the situation somewhat

    while ( my $line = <IN> ) { if ( $client->connected ) { print $client $line; } }

    however, this is of course not yet a real satisfactory solution to your problem of the client (potentially) disconnecting before you can complete writing the line.

    Update: BTW, some time ago, I was having a somewhat related problem (involving a pipe, not a socket, though...), in which I learned that such things can be trickier than I first thought... ;)   Maybe that discussion is of interest here, too.

      I'm sorry, yes in the actual program it is sent line by line (about 100 characters per line), I wrote the code from memory.

      I am surprised that no errors whatsoever are throw in my situation.

      Am I approaching this correctly by using "$client->connected" before writing anything to the socket? It just doesn't feel Perlish :-)