| View previous topic :: View next topic |
| Author |
Message |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Fri Jul 06, 2007 2:24 pm Post subject: Possible eggdrop bug when user disconnects from dcc chat? |
|
|
I wrote and maintain a TCL with roughly 2000 lines that implements a game of Mafia to be played on IRC with multiple players (it runs on irchighway). The game is played in a telnet session hosted by the bot. Note that I will only paste here code snippets, often taken from different locations in the script.
| Code: | listen $mafia_port script mafia_incoming pub
proc mafia_incoming {idx} {
global mafia_players
set dl [dcclist socket]
set myhost unknown
for {set i 0} {$i < [llength $dl]} {incr i} {
if {[lindex [lindex $dl $i] 0] == $idx} {set myhost [lindex [split [lindex [lindex $dl $i] 2] "@"] 1]}
}
set dl [dcclist script]
set clones 0
for {set i 0} {$i < [llength $dl]} {incr i} {
if {[lindex [lindex $dl $i] 0] != $idx} {
if {[string tolower [lindex [split [lindex [lindex $dl $i] 2] "@"] 1]] == [string tolower $myhost]} {set clones 1}
}
}
if {!$clones} {
control $idx mafia_line
} else {
killdcc $idx
}
} |
This is the code that handles incoming connections. It works perfectly. As you can see, mafia_line is the procedure that handles the messages received from the user. According to the eggdrop documentation, this procedure can also handle user disconnections, as a blank message is sent to it when the user disconnects - and blank messages are never passed to the procedure otherwise. So I set things up like this:
| Code: | proc mafia_line {idx text} {
set me [mafia_getplayerbyidx $idx]
set mynick [mafia_geti $me 1]
(...)
if {$text == ""} {
mafia_killplayer [mafia_geti $me 1]
mafia_echo "common" "0,1*** $mynick has disconnected from Mafia."
mafia_killcon [mafia_geti $me 0]
}
(...)
}
proc mafia_killcon {idx} {
global mafia_players
set me [mafia_getplayerbyidx $idx]
if {$me != {}} {
set mafia_players [lreplace $mafia_players $me $me]
}
if {[valididx $idx]} {
killdcc $idx
}
} |
This also works perfectly, with one single exception: mafia_echo is supposed to relay text to everyone who is connected to the game. This function, in this situation, does not work. It is used in a bazillion of other places in the script, as well as mafia_geti and mafia_getplayerbyidx, so they can't POSSIBLY be wrong. It's just that, in a procedure triggered by a player's disconnection, eggdrop does not seem to allow putdcc/putidx to be called. To confirm this, I have tried to manually use:
.tcl mafia_line "SomePlayersNickname" ""
The player was successfully disconnected AND the remaining players received the message, $mynick has disconnected from Mafia. So the only occasion in which players can't receive the message is when mafia_line is triggered by a user's disconnection.
Now, the Eggdrop documentation emphasizes that the programmer should be careful not to send messages to the IDX of the user who has just disconnected. While I was careful not to do that, I was wondering if Eggdrop doesn't somehow block ALL calls to putidx/putdcc during disconnect calls to the message handling procedure in order to stop the user from making this mistake, thus accidentally blocking calls to putidx/putdcc with legitimate (not yet disconnected) IDXs in these circumstances.
Any ideas?
EDIT/PS: Note that putidx/putdcc do not work in the situation described, but they do not output any errors either, and they do not halt the evaluation of the procedure. |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Fri Jul 06, 2007 5:52 pm Post subject: |
|
|
Are you sure that $text is "" when a user is disconnected? Try adding some putlogs to debug the problem. _________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Sat Jul 07, 2007 9:10 am Post subject: |
|
|
| Like I wrote, all the other commands in the IF are executed properly when a user is disconnected - both before and after the mafia_echo . The ONLY thing that doesn't work as expected is the putidx having no effect. It doesn't even halt the script execution, it's just ignored as if the statement wasn't there. But, like I previously wrote, if I manually call the procedure putidx will work as expected. |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Sat Jul 07, 2007 1:07 pm Post subject: |
|
|
That's why I asked, if it's acting as if the expression does not exists that means the expression is not being satisfied. _________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Sat Jul 07, 2007 7:09 pm Post subject: |
|
|
Either you don't understand or you aren't explaining yourself clearly. Just in
case it's the former, here it goes:
In bold are the statements the bot evaluates and executes. Imagine the player had the IDX 25 .
SITUATION 1) .tcl mafia_line 25 ""
if {$text == ""} {
mafia_killplayer [mafia_geti $me 1]
mafia_echo "common" "0,1*** $mynick has disconnected from Mafia."
mafia_killcon [mafia_geti $me 0]
}
SITUATION 2) Player 25 disconnects
if {$text == ""} {
mafia_killplayer [mafia_geti $me 1]
mafia_echo "common" "0,1*** $mynick has disconnected from Mafia."
mafia_killcon [mafia_geti $me 0]
}
Exactly what do you mean by an expression not being satisfied? |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Sat Jul 07, 2007 8:17 pm Post subject: |
|
|
You can never know if the bolded set commands are being executed unless you add some putlog line to see if the code is actually being processed.
I was talking about the if-expression. Just add something like
| Code: | if {$text == ""} {
mafia_killplayer [mafia_geti $me 1]
putlog "The player disconnected!"
mafia_echo "common" "0,1*** $mynick has disconnected from Mafia."
mafia_killcon [mafia_geti $me 0]
} |
Just to see if this putlog is executing when a player disconnects, if it doesn't then it means that the if-expression was not satisfied (meaning $text != ""). _________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Sat Jul 07, 2007 8:56 pm Post subject: |
|
|
| I know that they are being executed because mafia_killplayer and mafia_killcon both perform vital changes to variables and those changes are being performed. I repeat, ONLY the putidx commands in mafia_echo are ignored. I tested this exhaustively. |
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Sun Jul 08, 2007 7:39 am Post subject: |
|
|
| As you have suggested, I added some putlogs here and there to try and narrow down the problematic code. mafia_echo has a check that uses the valididx function to confirm that an IDX currently exists before using putdcc on it. I added a putlog there, and as soon as someone disconnected, the partyline was flooded with invalid idx messages - apparently when mafia_line is called with "" due to a disconnection, valididx considers ALL IDXs are invalid, for some reason... |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Sun Jul 08, 2007 9:03 am Post subject: |
|
|
That's weird; a quick solution would be delaying the send to all idxs in case of a disconnection. _________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Sun Jul 08, 2007 11:17 am Post subject: |
|
|
I tried going around the valididx check in case of a disconnection but it doesn't work either - putidx returns invalid idx for all IDXs
I think I understand what you mean. So should I make a queue, add messages to that queue in case of a disconnection and have a timer calling a procedure to output messages from that queue? That might work. |
|
| Back to top |
|
 |
Sir_Fz Revered One

Joined: 27 Apr 2003 Posts: 3793 Location: Lebanon
|
Posted: Sun Jul 08, 2007 3:42 pm Post subject: |
|
|
| Anansi wrote: | | I think I understand what you mean. So should I make a queue, add messages to that queue in case of a disconnection and have a timer calling a procedure to output messages from that queue? That might work. |
Yes, a simple [utimer] which calls the putidx for everybody after a few seconds should do the trick. _________________ Follow me on GitHub
- Opposing
Public Tcl scripts |
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Sun Jul 08, 2007 4:32 pm Post subject: |
|
|
| But it's still only a workaround for the bug. mafia_killplayer also uses mafia_echo and calls other procedures that also use mafia_echo, so such a workaround will be pretty hard to implement - I'll have to mess up my otherwise clean code by adding tests and globals all over the place. Still, thanks for the help. |
|
| Back to top |
|
 |
heidel Voice
Joined: 12 Jul 2007 Posts: 1
|
Posted: Thu Jul 12, 2007 3:43 pm Post subject: |
|
|
Indeed. I doubt there's a cure, unless you want to modify the eggdrop source. Btw, I appended some code that I used to reproduce this odd problem. And if you want another hack solution: use the undocumented function putdccraw. It works but might not be as safe.
| Code: |
proc putraw {idx text} {
append text "\n"
putdccraw $idx [string length $text] $text
}
proc test_listen:control {idx text} {
if {$text != ""} {
putlog "test_listen:control($idx) RECV: $text"
} else {
putlog "test_listen:control($idx) CLOSED"
putlog "Notifying all other script connections:"
foreach {dcc} [dcclist script] {
foreach {dccidx handle hostname type other timestamp} $dcc {
if {$dccidx != $idx} {
putlog " $dccidx ($hostname)"
# putdcc doesn't work: invalid idx
#putdcc $dccidx "Disconnected sock $idx..."
# hack with undocumented function putdccraw (wrapped in putraw)
putraw $dccidx "Disconnected sock $idx..."
}
}
}
}
}
proc test_listen:grab {newidx} {
putlog "test_listen:grab CONNECT"
control $newidx test_listen:control
}
listen 31234 script test_listen:grab
|
|
|
| Back to top |
|
 |
Anansi Voice
Joined: 02 Jul 2007 Posts: 16
|
Posted: Tue Jul 17, 2007 2:00 pm Post subject: |
|
|
Thanks Sorry it took so long to reply, but I had to study for an exam these past few days, so I had no time for Tcl. |
|
| Back to top |
|
 |
|