in reply to Re: thread:shared
in thread thread:shared

zentara,

your version
print $socket $chat[$i], $EOL if ( $1 ne $ID && $2 ne $kill);
sends the $ID to all the Clients and there it has absolutely no meaning.
The Reader adds the (internal) $ID:
push @chat, "$self->{ID}\t$1";
and the Writer should remove this ID:(little changed)
foreach ( @chat[$E{$ID} .. $#chat] ) { # spilt into ID and incomming line /(.+?)\s(.+)[\n\r]*/; # send only line print $socket $2,$EOL if ( $1 ne $ID && $2 ne $kill); }
So a Writer does not send
1. if a line is from its corresponding Reader:   $1 ne $2
2. if a line has the kill-code (no matter by whom):  $2 ne $kill

If you want the Client to get back his own line just change print $socket .. to:
print $socket $2,$EOL if ( $2 ne $kill );
Well, when I removed my stupid bug (look at the code,
a few lines above is a simular sitiation, where I can 'empty' $Elm),
this memory access error disappeared. So I think it is from there.

In case of any problem may be you better mail me directly:
g o o l y @ g m x . a t
(valid until I get tooo much spam.)

have fun chatting,
carl

Replies are listed 'Best First'.
Re: Re: Re: thread:shared
by zentara (Cardinal) on Dec 18, 2003 at 14:28 UTC
    " your version
    print $socket $chat[$i], $EOL if ( $1 ne $ID && $2 ne $kill);
    sends the $ID to all the Clients and there it has absolutely no meaning."

    Well it's working for me. What I get echoed to all clients is the tmp ID followed by a space, followed by the client message. I find this useful, because it tells me which client originated the message. The following is how I figured it out. I just printed the chatline, and saw the needed info was in there. The chatline I get is a list, the first element is the unique client ID, and the second is the message sent. It isn't split into $1 and $2. Anyways, we both have it working the way each of us likes it best, so it really is no problem.

    for my $i ( $E{$ID} .. $#chat ) { $chat[$i] =~ /(.+?)\s(.+)[\n\r]+/; print "chatline->$chat[$i]\n"; print "In writerrun \$1->$1 \$2->$2\n"; print $socket $chat[$i],$EOL; #if ( $1 ne $ID && $2 ne $ki +ll ); #what gets echoed is : Wzghb2n3 foobarfoobarfoobar

    The bigger problem is the threads leaking. You observe it as the first writer not destroying itself. As I mentioned, if you don't detach $r and $w, the server crashing goes away, but there is a thread leak when you kill and restart clients. But it's a clue. I've put the detach back in, and am working on a way of "joining" the threads when they are finished. It only seems that the first thread has this problem, and maybe it has something to do with that line in the reader next if ( $NoClient < 2 ); ? It prevents the last @chat broadcast? Possible?

    Sooner or later, I will find a way. I will let you know at your email address what I find. Of course, you may be successful before me, if so post it in the Snippets section. This is nice useful code, which I'm sure is sought after by many newbies. Relatives are arriving today for the holiday parties, so I may be slowed down. :-)

      (I think I've allready posted a reply, but I can't see it, so here's my second try).
      The line in the Reader's loop:
      next if ($NoClient < 2)
      directly corresponds to my wish (and purpose) not to echo the input back to the Client: If only 1 Client is connected, there is nothing to send, so don't push anything into @chat.

      But you can delete this line without any side effect - I think. If this line is deleted the input is pushed into @chat. Then the Writer tries to sent those lines but won't because he is not allowed to do
      print $socket .. if ($1 ne $ID ..);
      after that he is eliminating them from @chat. Just to prevent the Writer to do this for nothing I added the a.m. line.

      Writer-Zombie
      When the socket broke the Reader pushes his kill-code into @chat no matter how many Clients are left and on this the Writer is asked to work (cond_wait) and will find his 'personal' kill-code and he'll die.
      As soon as I moved the 'kill-code-detection' from the wile (1) loop
      -- formally I had: while ( "@chat" !~ ($ID\s$kill/){..
      this place is after cond_wait and after the elimination of sent lines --
      rigth after the cond_wait, I have had no more zombies. I pretty much convinced that this was the cause for this problem.

      The memory access error I had went away as soon as I removed my bug splitting the empty $Elm. It could be that this is a mistake either of Perl or thread (thread:shared) or even Linux. It would be ok if the program crashes, but not in that way - I think.

      I wish you and your relatives nice christmas days
      here in Vienna we might get snow the next days, you too,
      Carl
        Merry Christmas to you too. :-) Thanks for the explanations. The only problem I'm still seeing in my testing is that zombie thread. What happens for me depends on my testing. I'm starting the server, then connect with 3 clients. If I disconnect the clients, in the creation order, 1..2..3, first kill 1, then 2 then 3, there is no zombie thread left. But if I kill them off 3..2..1, then there is the zombie thread, and the server will crash when I restart the clients and send a message. I tried to not detach the $r and $w, and this problem goes away, the threads dissapear from the socklist, but they are still leaking internally, and the tid count from threads->list starts to climb. And my current approach is to try to use your Elm to join threads when they are no longer active. It is departing from your method though. Anyways, thanks for posting this. I learned alot.
      I enterd in the Reader the line:
      next if ($NoClient < 2);
      for speed and for 'economical' reasons. If only 1 Client is 'chatting' that would mean (for my purpos: sending results that have to be added to file - this part I elimiated), that there is no need to push anything into @chat.

      But you just can skip this line without any side effects. @chat would only be a bit bigger and the Writer is called just to eliminate those lines: I think the Writer gets a signal on (or by?) cond_wait, he will try to send those lines but won't send them because the lines are from his corresponding reader, then those lines are deleted.

      This cannot be responsible for the fact that some time ago sometimes a Writer did not die. The Reader leaves the loop when his socket broke, then outeside the loop he is pushing the 'kill-code' into @chat and this should call the Writer. He detects the 'kill-code' together with his ID and he will leave the loop. Due to the fact that he is the last to die, the Writer does all the admin stuff, I think it's usefull that way.
      carl