Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

socket, send and script crash

SouldrinkerSouldrinker Posts: 143Member
Hi,

I'm really fed up with this one. After hours of using google and testing arround, still no solution. My nerves are at their end at the moment, so I hope anyone here could help me. My script is as follows:

[code]
anakin.pl
#!/usr/bin/perl

# anakin.pl
#
# main file for the anakin-chatserver system
#
# version: 0.0.1
# @created: 2008-01-25
# @modified: 2008-01-26

use strict;
use IO::Socket;
use IO::Select;

print "anakin chat system (version 0.0.1) starting up...
";
print "binding reading socket...
";
my $listenRead = IO::Socket::UNIX->new(
Local => '/tmp/anakinread.sock',
Listen => 1,
Reuse => 0,
Blocking => 0) or die $!;
print "anakin chat system (version 0.0.1) running - bound on local unix domain socket...
";

my $selectread = IO::Select->new($listenRead);
my @ready;

while(1) {
for my $socketread ($selectread->can_read) {
if($socketread == $listenRead) {
my $new = $listenRead->accept;
print "[anakin:] got new connection with handle " . $new->fileno . "
";
my $line="";
$new->recv ($line,255);
if ($line eq "reading_connection") {
print "[anakin:] established a reading connection for handle " . $new->fileno . " peername: " . $new->peername . "
";
$selectread->add ($new);
} else {
print "[anakin:] got data from handle " . $new->fileno . " - Will broadcast it to reading clinets
";
print "[anakin:] client broadcasts: " . $line . "
";

for my $eachsocket ($selectread->handles) {
if ($eachsocket==$listenRead) {
next;
} else {
print "[anakin:] sending data to client...
";
$eachsocket->send ($line . "
") or print "other side closed connection...
";
}
}

$new->close;
}
}
}
}
[/code]

Simple script, wich opens a unix domain socket and accepts reading and writing connections - a chat script at all. The tricky thing is the line, which sends the written data to the connected clients. Imho the "or print" command, would take care of, if the client has disconnected and can not receive data anymore, but everytime this case is given, the script crashes... What do I have to do, to determinate, if the client has disconnected? Error handling in perl seems to come from stone age or some what...

Comments

  • JonathanJonathan Posts: 2,914Member
    Hi,

    The "or" trick works just fine if you are testing the return value. Apart from this module chose to throw an exception instead of use the return value to say the sending fails (which probably makes sense, in that it can indicate whether there was an error sending the data, or whether you just tried to send zero bytes).

    So you need to wrap the line in an eval { } block to catch the exception, then check if one happened.

    [code]eval {
    $eachsocket->send ("$line
    ");
    };
    if ($@) {
    print "other side closed connection...
    ";
    }[/code]

    Many languages provide library implementers the choice of throwing exceptions or having return values; there's nothing stone age here. :-)

    Jonathan
    ###
    for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");
  • SouldrinkerSouldrinker Posts: 143Member
    Hi,

    well, ok - I tried to use "eval" to catch the error before. Now I put it in again, and tested. The script still crashes if I do as follow:

    1. start up the server
    2. build up a connection, sending "reading_connection" and listen to data from socket
    3. kill the listening client by strg+c the script I use to test
    4. start another script, which sends 255 byte of data to the server and closes the connection

    I assume, that the crash occours, when the server tries to send the 255 byte of data to the "reading_connection" client, which I killed by terminating the script. If I don't kill the reading script and use my "send 255 byte data script", the reading client get's the data from server and the script doesn't crash...

    Can it be, that the crash has something to do with the version of perl I'm using? On the system I am testing on, rpm -q perl gives: perl-5.8.5-36.RHEL4, so i'ts perl 5.8.5 - I guess this is quite the actual version... As I read in the perl documentation, the eval { ... } realy should catch the error, I can't imagine why it does not in this specific case :-/

    : Hi,
    :
    : The "or" trick works just fine if you are testing the return value.
    : Apart from this module chose to throw an exception instead of use
    : the return value to say the sending fails (which probably makes
    : sense, in that it can indicate whether there was an error sending
    : the data, or whether you just tried to send zero bytes).
    :
    : So you need to wrap the line in an eval { } block to catch the
    : exception, then check if one happened.
    :
    : [code]: eval {
    : $eachsocket->send ("$line
    ");
    : };
    : if ($@) {
    : print "other side closed connection...
    ";
    : }[/code]:
    :
    : Many languages provide library implementers the choice of throwing
    : exceptions or having return values; there's nothing stone age here.
    : :-)
    :
    : Jonathan
    : ###
    : for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    : (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    : /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");

    best regards,

    sebastian besteman
    ceo
    solvention

    http://solvention.de
    s.besteman@solvention.de
  • SouldrinkerSouldrinker Posts: 143Member
    Solved the problem... system administrating lesson #1: signals. I should have recognize, that sending data to a "dead socket" will resultate in a SIG_PIPE, which I have to catch. If I don't do so, the standard handling will take effect, which in this case is: abort the execution. So, now I have a signal handler, which catches SIG_PIPE and will close the socket. Thanks for the help
    best regards,

    sebastian besteman
    ceo
    solvention

    http://solvention.de
    s.besteman@solvention.de
  • rinoobrinoob Posts: 14Member
    : Solved the problem... system administrating lesson #1: signals. I
    : should have recognize, that sending data to a "dead socket" will
    : resultate in a SIG_PIPE, which I have to catch.

    You might never read this, but thanks for posting the followup. I've been dealing with this problem all day. I searched endlessly for a solution with no luck. Finally, I stumbled on this thread, and catching the PIPE signal works. Now I can get back to work. I'm glad you posted.
Sign In or Register to comment.