Login
User Name:

Password:



Register
Forgot your password?
Vote for Us!
tintin++ ogg sound player script for linux
Author: Robert Smith
Submitted by: Vladaar
6Dragons ogg Soundpack
Author: Vladaar
Submitted by: Vladaar
6Dragons 4.4
Author: Vladaar
Submitted by: Vladaar
LoP 1.46
Author: Remcon
Submitted by: Remcon
LOP 1.45
Author: Remcon
Submitted by: Remcon
Users Online
CommonCrawl, Bing

Members: 0
Guests: 7
Stats
Files
Topics
Posts
Members
Newest Member
481
3,740
19,396
629
DarrenPayn
Today's Birthdays
There are no member birthdays today.
Related Links
» SmaugMuds.org » Codebases » SmaugFUSS » Leave progs can crash the MUD...
Forum Rules | Mark all | Recent Posts

Leave progs can crash the MUD by closing an exit
< Newer Topic :: Older Topic >

Pages:<< prev 1 next >>
Post is unread #1 Aug 31, 2006, 12:17 pm   Last edited Sep 4, 2006, 3:45 pm by Valcados
Go to the top of the page
Go to the bottom of the page

Valcados
Apprentice
GroupMembers
Posts63
JoinedAug 25, 2006

In mud.h, find this:
typedef struct extracted_char_data EXTRACT_CHAR_DATA;


Below it, add this:
typedef struct  EXTRACTED_EXIT extracted_exit;


In mud.h, find this:
struct extracted_char_data
{
   EXTRACT_CHAR_DATA *next;
   CHAR_DATA *ch;
   ROOM_INDEX_DATA *room;
   ch_ret retcode;
   bool extract;
};


Below it, add this:
struct EXTRACTED_EXIT
{
  extracted_exit *next;
  extracted_exit *prev;
  EXIT_DATA *exit_ptr;
};


In mud.h, find this:
extern EXTRACT_CHAR_DATA *extracted_char_queue;


Below it, add this:
extern extracted_exit *first_extracted_exit;
extern extracted_exit *last_extracted_exit;


In mud.h, find this:
char *rev_exit args( ( short vdir ) );


Below it, add this:
bool is_exit_extracted args(( EXIT_DATA *xit ));


In act_move.c, find this:
      for( fch = from_room->first_person; fch && ( count < chars ); fch = nextinroom )
      {
         nextinroom = fch->next_in_room;
         count++;
         if( fch != ch  /* loop room bug fix here by Thoric */
             && fch->master == ch && fch->position == POS_STANDING )
         {
            act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
            move_char( fch, pexit, 0 );
         }
      }


Change it to this:
      for( fch = from_room->first_person; fch && ( count < chars ); fch = nextinroom )
      {
         nextinroom = fch->next_in_room;
         count++;
         if( fch != ch  /* loop room bug fix here by Thoric */
             && fch->master == ch && fch->position == POS_STANDING )
         {
            if ( is_exit_extracted( pexit ) )
            {
              act( AT_ACTION, "The entrance closes behind $N, preventing you from following!", fch, NULL, ch, TO_CHAR );
              continue;
            }
            act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
            move_char( fch, pexit, 0 );
         }
      }


Somewhere (for example at the very bottom) add this function to act_move.c:

bool is_exit_extracted( EXIT_DATA *xit )
{
  extracted_exit *ee;

  for ( ee = first_extracted_exit; ee; ee = ee->next )
    if ( ee->exit_ptr == xit )
      return TRUE;

  return FALSE;
}


In db.c, find this:
EXTRACT_CHAR_DATA *extracted_char_queue;


Below it, add this:
extracted_exit *first_extracted_exit;
extracted_exit *last_extracted_exit;


In handler.c, find this:
void extract_exit( ROOM_INDEX_DATA * room, EXIT_DATA * pexit )
{
   UNLINK( pexit, room->first_exit, room->last_exit, next, prev );
   if( pexit->rexit )
      pexit->rexit->rexit = NULL;
   STRFREE( pexit->keyword );
   STRFREE( pexit->description );
   DISPOSE( pexit );
}


Change it to this:
void extract_exit( ROOM_INDEX_DATA * room, EXIT_DATA * pexit )
{
    extracted_exit *ee;

    CREATE( ee, extracted_exit, 1 );
    ee->exit_ptr = pexit;
    LINK( ee, first_extracted_exit, last_extracted_exit, next, prev );

   UNLINK( pexit, room->first_exit, room->last_exit, next, prev );
   if( pexit->rexit )
      pexit->rexit->rexit = NULL;
   STRFREE( pexit->keyword );
   STRFREE( pexit->description );
}


In update.c, in function void aggr_update, find this:
    struct act_prog_data *apdtmp;


Below it, add this:
extracted_exit *ee;


In update.c, in fuction void aggr_update, find this:
   /*
    * Just check descriptors here for victims to aggressive mobs
    * We can check for linkdead victims in char_check   -Thoric
    */


Right above it, add this:
    while ( ( ee = first_extracted_exit ) != NULL )
    {
      UNLINK( ee, first_extracted_exit, last_extracted_exit, next, prev );
      DISPOSE( ee->exit_ptr );
      free( ee );
    }


And that should fix you right up.

EDIT: One last thing, since you guys are concerned about proper memory cleanup at exit. I haven't looked closely at your memory cleanup changes, so I don't know off hand whether something which is routinely cleaned by aggr_update needs to be considered for your special exit cleanup. I'll leave that for you guys to figure out.
       
Post is unread #2 Aug 31, 2006, 2:41 pm
Go to the top of the page
Go to the bottom of the page

Conner
Sorcerer
GroupMembers
Posts870
JoinedMay 8, 2005

Boy, this one's not exactly a little minor fix, is it?
       
Post is unread #3 Aug 31, 2006, 3:39 pm
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,874
JoinedJul 26, 2005

I changed
            act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
            move_char( fch, pexit, 0 );

to this
            act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
            move_char( fch, get_exit( from_room, door ), 0 );

It stopped the crashing from it and seems to work fine.
       
Post is unread #4 Aug 31, 2006, 4:33 pm
Go to the top of the page
Go to the bottom of the page

Conner
Sorcerer
GroupMembers
Posts870
JoinedMay 8, 2005

Is that in addition to, or instead of, what Valcados posted above?
       
Post is unread #5 Aug 31, 2006, 4:40 pm
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,874
JoinedJul 26, 2005

Thats the only change I did. Granted I never tested his (which if handled right and allows the people following to move to the new room correctly it might be cool). I only mainly wanted to take care of the possible crashing issue and personaly I think if someone uses a leave program to close the exit chances are they don't want everyone following suit without doing what ever they need to, to get the door to open back up. That one change stopped mine crashing from it though.
       
Post is unread #6 Aug 31, 2006, 7:59 pm
Go to the top of the page
Go to the bottom of the page

Conner
Sorcerer
GroupMembers
Posts870
JoinedMay 8, 2005

So, doing both would be a good thing you figure?
       
Post is unread #7 Aug 31, 2006, 10:45 pm   Last edited Aug 31, 2006, 10:59 pm by Valcados
Go to the top of the page
Go to the bottom of the page

Valcados
Apprentice
GroupMembers
Posts63
JoinedAug 25, 2006

Remcon, that is very nice :cool: unfortunately it doesn't quite work. move_char interprets a NULL exit argument as "character will crash drunkenly into an obstacle". At least that's what my version does, which I believe is stock, but I'm on an office computer right now and can't download stock or smaug FUSS here.

But that is still way better than the whole MUD crashing =) in fact that could be pretty cool if you did it intensionally.

Alcoholic's Anonymous
You are standing in the Alcoholic's Anonymous. To leave, you need merely go north.
Exits: north.
Bob the group leader is standing here.

Bob leaves north.
You follow Bob.
In your drunken stupor you trip over your own feet and tumble to the ground.


:grinning:

Now, a slightly better method along those means would be to change it to something like
if ( get_exit( from_room, door ) )
{
  act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
  move_char( fch, get_exit( from_room, door ), 0 );
}


This still does not work, but for a very subtle reason. One of the lesser-known features in SMAUG is the ability to have multiple exits in the same direction. The group leader could step through one, which gets deleted, and then his followers all step through the other one. Oops! :devil:
       
Post is unread #8 Sep 1, 2006, 3:15 am   Last edited Sep 1, 2006, 3:20 am by Remcon
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,874
JoinedJul 26, 2005

Not sure why it said that to you, on mine it did this
Remcon leaves north.
You follow Remcon.
Alas, you cannot go that way.

The one following on yours must have been drunk to get that response (or maybe there was some bug that has already been fixed in SmaugFUSS).

Also you shouldn't actually be able to have more then 1 exit per direction in a room. Of course you could easily set something up to as it closes one exit open another and on a leave program end up with each one going to a different room to split them up (would probably be great for followers getting lost from the leader or something) lol.
       
Post is unread #9 Sep 1, 2006, 4:17 am
Go to the top of the page
Go to the bottom of the page

kiasyn
Magician
GroupMembers
Posts121
JoinedJun 30, 2006


help advancedexits
Help level: 800
SMAUG supports having more than one exit in the same direction, as well as
the special direction 'somewhere', represented by a '?'.

If you already have an exit leading north, and would like another one, use
a plus sign '+' in front of the direction:
redit exit +n 3001 - Adds another exit north to room 3001

To modify an extra exit like this, or to remove it, you'll have to refer to
it by number:
redit exit #2 3002 - Change the second exit to go to room 3002
(to know what number an exit is, do an "rstat";)

For someone to be able to use the second north exit, you have to set one of
the extra flags (see EXFLAGS) like CAN_CLIMB. It's also usually a good idea
to set the HIDDEN flag for any special exit so that it looks nicer to those
with autoexits on.

The AUTO flag makes it possible to go in a direction by simply typing the
keyword for that exit:
redit exit ? 3001 - Create a 'somewhere' exit to 3001
redit exflags ? auto hidden - Set the proper flags
redit exname ? swim - Set the keyword "swim"
... here, if a player types 'swim' in the room they will move to room 3001

       
Post is unread #10 Sep 1, 2006, 5:53 am
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,874
JoinedJul 26, 2005

mpopenpassage doesn't make use of allowing more then one exit in a direction, and mpclosepassage only closes passage type exits. Considering these are designed for mobs to use for programs its the main thing to deal with when dealing with mob programs when it comes to exits. Technically yes you can make more then one exit in a given direction, but it doesn't make my previous statement about you shouldn't have more then one exit in a direction any less correct. Considering no one has noticed this problem before chances are they don't make much use of closeing an exit out useing a leave program anyways lol.
       
Post is unread #11 Sep 1, 2006, 6:38 am
Go to the top of the page
Go to the bottom of the page

Valcados
Apprentice
GroupMembers
Posts63
JoinedAug 25, 2006

Remcon said:

Not sure why it said that to you, on mine it did this
Remcon leaves north.
You follow Remcon.
Alas, you cannot go that way.

The one following on yours must have been drunk to get that response (or maybe there was some bug that has already been fixed in SmaugFUSS).
Ah, I looked more closely and I see you're quite right. A NULL pointer means "character might crash into a drunken obstacle--- if they are drunk". Anyway, it's not worth fighting over, I think for all practical intents and purposes Remcon's solution should work :biggrin: I'm just glad I learned something out of the bargain
       
Post is unread #12 Sep 1, 2006, 7:05 am
Go to the top of the page
Go to the bottom of the page

Remcon
Geomancer
GroupAdministrators
Posts1,874
JoinedJul 26, 2005

Most of the people here (myself included) don't fight about things, we will of course debate it etc... and along the way we all get to learn maybe new ways of doing something etc... Your way for example (although I haven't tried it) might very well let all of the followers get through the exit before closeing it out. It just depends on what kind of thing your looking for in the end. Personaly I try to keep down on alot of stuff while still keeping it functional. I could see either way being useful. If someone wants to make it so that the exit only closes after all went through useing mine for example they could very well use an ifcheck to make sure no mortals are left in the room first (That would close the exit after the last mortal left the room). So its all in how you want something. :), The big point here was to stop it crashing and both ways fix the crashing issue.

Incase I haven't already said it...Nice find and ty for posting it. I don't make use of programs alot yet and haven't found all the possible issues lol.
       
Post is unread #13 Sep 4, 2006, 9:27 am
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,644
JoinedJan 1, 2002

*adds to the debate*

Could we not do something like this instead?
         if( fch != ch  /* loop room bug fix here by Thoric */
             && fch->master == ch && fch->position == POS_STANDING )
         {
            if( !pexit )
            {
              act( AT_ACTION, "The entrance closes behind $N, preventing you from following!", fch, NULL, ch, TO_CHAR );
              continue;
            }
            act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
            move_char( fch, pexit, 0 );
         }


Should prevent the crash, as well as issue the information message to the player in a proper manner. Rather than relying on the behavior of a NULL exit.
       
Post is unread #14 Sep 4, 2006, 10:54 am
Go to the top of the page
Go to the bottom of the page

Valcados
Apprentice
GroupMembers
Posts63
JoinedAug 25, 2006

The crash is caused when the exit pointed to by pexit is free'd and overwritten by code outside of move_char, and then pexit, which is never NULLed or otherwise changed, is used in the loop. So the problem is not that pexit is NULL, but that the thing pexit points to is no longer well defined.
       
Post is unread #15 Sep 4, 2006, 11:07 am
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,644
JoinedJan 1, 2002

Well when do_mp_close_passage is called, if the exit is being destroyed, extract_exit is called to remove it. extract_exit will unlink it from the room, free the strings, and then DISPOSE the exit pointer. In this case, pexit. So pexit will in fact be NULL by this point and a simple check on that should work. There should be no way for the "thing that pexit points to" to be undefined or whatever since it's been properly removed from memory. The people following the leader won't be able to move through the exit since it no longer exists, and they should be told something more informative than "you're drunk" or "you can't go there".
       
Post is unread #16 Sep 4, 2006, 11:20 am
Go to the top of the page
Go to the bottom of the page

Valcados
Apprentice
GroupMembers
Posts63
JoinedAug 25, 2006

No, pexit is a local, non-static pointer whose scope does not extend outside of move_char. It is a copy of the pointer which was passed by whatever called move_char (for example do_north). So to set it to null, the DISPOSE would have to actually be inside the move_char function. There's no way for things outside of move_char to edit the pexit pointer unless a pointer to the pexit pointer were passed somewhere as a function argument.

Please correct me if I'm wrong here :redface:
       
Post is unread #17 Sep 4, 2006, 12:06 pm
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,644
JoinedJan 1, 2002

Ok, I think I see your point. So if that's the case ( which seems logical ) then I would think this should work:

         if( fch != ch  /* loop room bug fix here by Thoric */
             && fch->master == ch && fch->position == POS_STANDING )
         {
            if( !get_exit( from_room, door ) )
            {
              act( AT_ACTION, "The entrance closes behind $N, preventing you from following!", fch, NULL, ch, TO_CHAR );
              continue;
            }
            act( AT_ACTION, "You follow $N.", fch, NULL, ch, TO_CHAR );
            move_char( fch, pexit, 0 );
         }


The main reason I'm stretching to find a simpler solution here is I don't like having to add extra complexity for isolated cases. Especially ones that require placement in the update handlers.
       
Post is unread #18 Sep 4, 2006, 1:02 pm   Last edited Sep 4, 2006, 1:04 pm by Valcados
Go to the top of the page
Go to the bottom of the page

Valcados
Apprentice
GroupMembers
Posts63
JoinedAug 25, 2006

As I pointed out earlier, the problem with this strategy is the fact there can be multiple exits in the same direction. Someone else pointed out this isn't a major problem, because mpopenpassage doesn't have support for the multiple exits, and mpclosepassage only closes passage flagged exits. Of course, an exit can be passage flagged without having been created by mpopenpassage, namely if an imm sets the flag manually, so the problem does technically remain, albeit in an exceedingly unlikely way.

It's all a nonissue anyway, you may do as you see fit :redface:

Regarding the uneasiness about adding things to the update handlers: I'm not sure why you are uneasy about this. Consider how character extraction works: the character is not free'd until the next pulse, when clean_char_queue is called. You could theoretically change it so characters are free'd immediately upon extraction, but this would have a majorly destabilizing effect and require subtle, careful modification of hundreds of lines of code: you'd probably have to make nontrivial surgical modifications everywhere the "char_died" function is called. It's just not worth it for the negligible performance increase. As for the snippet I posted here, even if we assume that every single pulse 100 exits get deleted MUD-wide (and this is a lot of exit deletion!!) then the performance cost is probably smaller than what would be incurred by installing a new area with 100 mobs walking around.

One reason for the solution I used is that it adds more flexibility: the is_exit_extracted function is useful outside of move_char.

But again, this is all a lot of discussion over a very small problem, please feel free to use any fix you like :smile: Though if you don't use mine, please don't put me as the fixer, for example Remcon posted a partial fix above which is similar to what you just posted :alien:

And thanks once more for the rocking job you do coordinating everything :biggrin:
       
Post is unread #19 Sep 7, 2006, 8:47 pm
Go to the top of the page
Go to the bottom of the page

Samson
Black Hand
GroupAdministrators
Posts3,644
JoinedJan 1, 2002

I think ultimately the issue here is a crash was reported with passage exits. The solution offered seemed excessive to some of us. It is afterall an edge case bug really since exits don't just up and disappear at random. If they did then your fix would certainly be much more appropriate.

So I think we'll be using the specific fix for this issue. Though I would still be interested in knowing what is_exit_extracted could be used for beyond this particular issue.
       
Pages:<< prev 1 next >>