Warning: This message is somewhat long, it describes the steps to reproduce a bug, and discusses a way to fix it. I have found a bug on CircleMUD 3.0 bpl18, envolving the close_socket() and the SWITCH command. Here is a simple way to reproduce it (greetings and motds stripped): -- First: find a mob to switch into. -- 500H 100M 82V > go aglandiir [ 3375] The Lair [ INDOORS NO_TRACK PRIVATE ] (...) The Dragon Prince, Aglandiir, sits here looking at you curiously. ...he glows with a bright light! 500H 100M 82V > switch aglandiir Okay. Aglandiir> -- At this point, we break our connection. -- ^] telnet> close Connection closed. Jun 16 21:38:30 :: WARNING: EOF on socket read (connection broken by peer) Jun 16 21:38:30 :: Closing link to: God. Jun 16 21:38:30 :: No connections. Going to sleep. -- And reconnect... -- $ telnet localhost 5000 Trying 127.0.0.1... Jun 16 21:38:32 :: New connection. Waking up. Connected to localhost. Escape character is '^]'. (...) By what name do you wish to be known? God Password: Jun 16 21:38:35 :: God [localhost] has reconnected. Reconnecting. 500H 100M 82V > switch aglandiir You can't do that, the body is already in use! -- Hugh?! Who is using its body??? -- 500H 100M 82V > purge aglandiir Okay. 500H 100M 82V > Welcome to CircleMUD! 0) Exit from CircleMUD. 1) Enter the game. 2) Enter description. 3) Read the background story. 4) Change password. 5) Delete this character. Make your choice: -- Mmmm... something is wrong... I have been sent to the menu... -- Make your choice: 1 Connection closed by foreign host. [1]+ Segmentation fault (core dumped) bin/circle 5000 -- Oops... -- I have found the bug in the close_socket() function: (...) if (d->character) { /* * Plug memory leak, from Eric Green. */ if (!IS_NPC(d->character) && PLR_FLAGGED(d->character, PLR_MAILING) && d->str) { if (*(d->str)) free(*(d->str)); free(d->str); } if (STATE(d) == CON_PLAYING || STATE(d) == CON_DISCONNECT) { struct char_data *link_challenged = d->original ? d->original : d->character; /* We are guaranteed to have a person. */ act("$n has lost $s link.", TRUE, link_challenged, 0, 0, TO_ROOM); save_char(link_challenged, NOWHERE); sprintf(buf, "Closing link to: %s.", GET_NAME(link_challenged)); mudlog(buf, NRM, MAX(LVL_IMMORT, GET_INVIS_LEV(link_challenged)), TRUE); link_challenged->desc = NULL; } else { (...) On the above case, d->original points to the God character, d->character points to Aglandiir. d->original->desc is already NULL, because CircleMUD considers linkless a player while it is switched. close_socket() sets link_challenged->desc to NULL, and leaves d->character->desc pointing to the descriptor that will be freed on the end of the function. Changing the code to... /* link_challenged->desc = NULL; */ if (d->original && d->original->desc == d) d->original->desc = NULL; if (d->character->desc == d) d->character->desc = NULL; ...fixed the bug for me. Probably, there is no need for doing the check and the clean on d->original->desc. I couldn't be able to imagine any circumstance where a character on d->original is linked to a descriptor. The SWITCH command does a 'ch->desc = NULL;' among other things. But a sanity check is better than running the risk. The second check, before doing the clean on d->character->desc, is a sanity check too. I think that is always expected that 'd->character->desc == d' and 'ch->desc->character == ch' on any normal circumstances. Regards, Juliano R Ferraz Captain ... one .. harmless ... little ... Tribble? I'm at the corner of Walk and Don't Walk. -- +---------------------------------------------------------------+ | FAQ: http://qsilver.queensu.ca/~fletchra/Circle/list-faq.html | | Archives: http://post.queensu.ca/listserv/wwwarch/circle.html | +---------------------------------------------------------------+
This archive was generated by hypermail 2b30 : 12/05/01 PST