in reply to Re^6: threads with shared variables across multiple instances of a module
in thread threads with shared variables across multiple instances of a module

If you included the full error message (including the line number), I'd have a chance of knowing which thread terminated abnormally.

If you included all the source code, I might stand a chance of trying it out for myself.

If you posted the code without the line numbers, I wouldn't have to strip them off.

And your code would be far easier (for you and me) to read and analyse if it was formatted consistently.

As it is, the most obvious problem is that %clients isn't declared (or shared) anywhere.

And BTW, this %clients = ( %clients, "$client_ip:$client_port" => fileno($client) ) ; is a really horrible way to add a new key/value pair to a hash. A simple:

$clients{ "$client_ip:$client_port" } = fileno($client);

is much easier to read and far more efficient.

You've also failed to do any locking of your shared hash. (Assuming it is actually declared & shared somewhere in the code you've omitted!)


Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
"I'd rather go naked than blow up my ass"

Replies are listed 'Best First'.
Re^8: threads with shared variables across multiple instances of a module
by zerg13new (Initiate) on Mar 29, 2010 at 07:48 UTC

    new attempt:

    This is WHOLE code of my server.pl at now

    ## my server ## 2010.03.05 #!/usr/bin/perl -w use strict; use IO::Socket; use threads; use threads::shared; ##use POSIX 'WNOHANG'; # for SIGNAL use constant BUFSIZE => 1024; our %clients:shared; my( $addr, $port ); $addr = &get_ip(); # get IP from interface ## get port print "enter port: "; while( <STDIN> ) { chomp($_); $port = $_; if ( /[0-9]{4,5}/ && $_ > 1024 ) { last; } print "either wrong value or port is deny, enter new value: "; } my $server = IO::Socket::INET -> new( LocalAddr => $addr, LocalPort => $port, Listen => 255, Type => SOCK_STREAM, Proto => 'tcp', Reuse => 1 ); die "can't create, bind or listen: $!\n" unless $server ; print "socket OK\n bind OK\n listen OK\n Server started at $addr:$port +\n"; warn "Server ready. Waiting for connections... \n"; threads -> create( \&to_client ) || die "$! \n"; # STDIN ## start threads to treat querys while( my $client = $server -> accept ) { my $client_ip = $client -> peerhost(); my $client_port = $client -> peerport(); $clients{ "$client_ip:$client_port" } = fileno( $client ); # a +dd new socket to %client print "got a connection from: $client_ip:$client_port $client\ +n"; $client -> autoflush; threads -> create( \&from_client, $client, $client_ip, $client +_port ) || die "$! \n"; #STDOUT } exit 0; ## ****************************************************** ## get local machine IP from interface sub get_ip { my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyna +me( 'localhost' ); my ($name1, $aliases1, $addrtype1, $length1, @addrs1) = gethos +tbyname( $name ); my $addr1 = inet_ntoa( $addrs1[0] ); return $addr1; } ## ****************************************************** ## send message to client or see list of client sub to_client { my ( $clnt_ip_port, $msg_t, $tmp ); while( sysread(STDIN, $tmp, BUFSIZE) ) { chomp $tmp; if( $tmp eq "list" ) { print "connect to this server:\n"; foreach my $z ( keys %clients ) { print "clien +t: $z $clients{$z}\n"; } } elsif ( $tmp =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d +{4,5}\s.*/ ) { ( $clnt_ip_port, $msg_t ) = ( $tmp =~ /(\d{1,3 +}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{4,5})\s(.*)/ ); if ( exists $clients{$clnt_ip_port} ) { ## try to send message my $client; my $fileno = $clients{$clnt_ip_port}; open $client, "+<$fileno" || die "$!\n +"; ##print "syswrite $clients{$clnt_ip_port} {$msg_t} \n"; syswrite( $client, $msg_t ) || die ": +$!\n"; } else { print "not exist client or empty mess +age!\n"; } } else { print "wrong value, check and see \"list\" of + clients!\n"; } } } ## ****************************************************** ## recive message from client sub from_client { my ( $sock, $clnt_ip, $clnt_port ) = @_;; my $msg_f; syswrite( STDOUT, "from $clnt_ip:$clnt_port: $msg_f" ) while s +ysread( $sock, $msg_f, BUFSIZE ); print "client at $clnt_ip:$clnt_port closed connection \n"; delete $clients{"$clnt_ip:$clnt_port"}; # delete socket from % +client $sock -> close; }

    OUTPUT of my server.pl:

    enter port: 1234 socket OK bind OK listen OK Server started at 127.0.0.1:1234 Server ready. Waiting for connections... got a connection from: 127.0.0.1:37725 IO::Socket::INET=GLOB(0x8d1ea38 +) list connect to this server: client: 127.0.0.1:37725 5 127.0.0.1:37725 qwerty Thread 1 terminated abnormally: : Bad file descriptor
    it is better ?? sorry for my illiteracy =)
Re^8: threads with shared variables across multiple instances of a module
by zerg13new (Initiate) on Mar 29, 2010 at 08:00 UTC

    new attempt:

    This is WHOLE code of my server.pl at now

    ## my server ## 2010.03.05 #!/usr/bin/perl -w use strict; use IO::Socket; use threads; use threads::shared; ##use POSIX 'WNOHANG'; # for SIGNAL use constant BUFSIZE => 1024; our %clients:shared; my( $addr, $port ); $addr = &get_ip(); # get IP from interface ## get port print "enter port: "; while( <STDIN> ) { chomp($_); $port = $_; if ( /[0-9]{4,5}/ && $_ > 1024 ) { last; } print "either wrong value or port is deny, enter new value: "; } my $server = IO::Socket::INET -> new( LocalAddr => $addr, LocalPort => $port, Listen => 255, Type => SOCK_STREAM, Proto => 'tcp', Reuse => 1 ); die "can't create, bind or listen: $!\n" unless $server ; print "socket OK\n bind OK\n listen OK\n Server started at $addr:$port +\n"; warn "Server ready. Waiting for connections... \n"; threads -> create( \&to_client ) || die "$! \n"; # STDIN ## start threads to treat querys while( my $client = $server -> accept ) { my $client_ip = $client -> peerhost(); my $client_port = $client -> peerport(); $clients{ "$client_ip:$client_port" } = fileno( $client ); # a +dd new socket to %client print "got a connection from: $client_ip:$client_port $client\ +n"; $client -> autoflush; threads -> create( \&from_client, $client, $client_ip, $client +_port ) || die "$! \n"; #STDOUT } exit 0; ## ****************************************************** ## get local machine IP from interface sub get_ip { my ($name, $aliases, $addrtype, $length, @addrs) = gethostbyna +me( 'localhost' ); my ($name1, $aliases1, $addrtype1, $length1, @addrs1) = gethos +tbyname( $name ); my $addr1 = inet_ntoa( $addrs1[0] ); return $addr1; } ## ****************************************************** ## send message to client or see list of client sub to_client { my ( $clnt_ip_port, $msg_t, $tmp ); while( sysread(STDIN, $tmp, BUFSIZE) ) { chomp $tmp; if( $tmp eq "list" ) { print "connect to this server:\n"; foreach my $z ( keys %clients ) { print "clien +t: $z $clients{$z}\n"; } } elsif ( $tmp =~ /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d +{4,5}\s.*/ ) { ( $clnt_ip_port, $msg_t ) = ( $tmp =~ /(\d{1,3 +}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{4,5})\s(.*)/ ); if ( exists $clients{$clnt_ip_port} ) { ## try to send message my $client; my $fileno = $clients{$clnt_ip_port}; open $client, "+<$fileno" || die "$!\n +"; ##print "syswrite $clients{$clnt_ip_port} {$msg_t} \n"; syswrite( $client, $msg_t ) || die ": +$!\n"; } else { print "don't exist client or empty me +ssage!\n"; } } else { print "wrong value, check and see \"list\" of + clients!\n"; } } } ## ****************************************************** ## recive message from client sub from_client { my ( $sock, $clnt_ip, $clnt_port ) = @_;; my $msg_f; syswrite( STDOUT, "from $clnt_ip:$clnt_port: $msg_f" ) while s +ysread( $sock, $msg_f, BUFSIZE ); print "client at $clnt_ip:$clnt_port closed connection \n"; delete $clients{"$clnt_ip:$clnt_port"}; # delete socket from % +client $sock -> close; }

    OUTPUT of my server.pl:

    enter port: 1234 socket OK bind OK listen OK Server started at 127.0.0.1:1234 Server ready. Waiting for connections... got a connection from: 127.0.0.1:37725 IO::Socket::INET=GLOB(0x8d1ea38 +) list connect to this server: client: 127.0.0.1:37725 5 127.0.0.1:37725 qwerty Thread 1 terminated abnormally: : Bad file descriptor
    it is better ?? sorry for my illiteracy =) yeap, i have not any locking, cause it will... in future ))

      Hm. This seems to be a platform specific problem--which OS are you running?--because your code (with one minor change), works for me:

      C:\test>perl 831580.pl 1234 enter port: 1234 socket OK bind OK listen OK Server started at 192.168.1.31:1234 Server ready. Waiting for connections... got a connection from: 192.168.1.31:52479 IO::Socket::INET=GLOB(0x4d7c +110) list connect to this server: client: 192.168.1.31:52479 4 192.168.1.31:52479 fred 192.168.1.31:52479 bill 192.168.1.31:52479 test 192.168.1.31:52479 more 192.168.1.31:52479 still more from 192.168.1.31:52479: from 192.168.1.31:52479: from 192.168.1.31:52479: from 192.168.1.31:52479: from 192.168.1.31:52479: from 192.168.1.31:52479: hfrom 192.168.1.31:52479: efrom 192.168.1.31: +52479: lfrom 192.168.1.31:52479: lfrom 192.168.1.31:52479: ofrom 192. +168.1.31:52479:

      I had to change 1 line:

      while( my $tmp = <STDIN> ) { ##sysread(STDIN, $tmp, BUFSIZE) ) + {

      because using sysread on STDIN means that no CRLF translation is done and so chomp doesn't do the right thing on my OS.

      I strongly suspect that your thread is dying because you are calling die.

      Try changing these two lines (remove the \n so that the line numbers are output), and then post your output:

      open $client, "+<$fileno" || die "$!"; syswrite( $client, $msg_t ) || die ": +$!";

      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.

        Hi, thanks a lot, cause code is working in Linux(debian) with Perl 5.10.0. I had mistake and it was here:

        open $client, "+<$fileno" || die "$!\n";

        must be "+<&$fileno", & - forget it =(

        BUT, don't work in windows XP SP3 with Strawberry Perl 5.10.1.1 (the latest version). Looks like message should send/recive in turn, otherwise blok input or output until send/recive. Perhaps cause i don't lock anything in my programms, althought it works in Linux. I'll try to change it soon. All i can say that in WinXP i didn't see in taskmanager more then one thread at process cmd-server or cmd-client.

        and now THANKS, i finished my homework (in Linux) 2 days ago, i'm happy =)

        THE BIGGEST thanks for the fastest respond at my troubles.