Pages:<< prev 1 next >>
#1 Aug 30, 2024 3:42 am
Last edited Aug 30, 2024 3:43 am by GatewaySysop
Conjurer
GroupMembers
Posts423
JoinedMar 7, 2005
Came across this by chance while tinkering with something new. Managed to produce a crash pretty readily and traced it back to here:
In update.c, function char_check( ):
That seems kinda... not smart.
Change to this:
In update.c, function char_check( ):
for ( ch = first_char; ch; ch = ch_next )
{
set_cur_char(ch);
ch_next = ch->next;
will_fall(ch, 0);
if ( char_died( ch ) )
continue;
That seems kinda... not smart.
Change to this:
for ( ch = first_char; ch; ch = ch_next )
{
set_cur_char(ch);
ch_next = ch->next;
if ( char_died( ch ) )
continue;
will_fall(ch, 0);
#2 Aug 30, 2024 4:59 am
Geomancer
GroupAdministrators
Posts1,923
JoinedJul 26, 2005
You might want another check for char_died after will_fall as well since it could cause them to die. Haven't tested it or anything but it might be possible that would cause a crash as well or at least some undesired results.
#3 Aug 30, 2024 12:57 pm
Conjurer
GroupMembers
Posts423
JoinedMar 7, 2005
Interesting thought. I did quite a bit of fall testing but hadn't been able to crash it. Can't hurt though!
#4 Aug 30, 2024 1:27 pm
Black Hand
GroupAdministrators
Posts3,690
JoinedJan 1, 2002
That portion of the function isn't the same as what's currently in the SmaugFUSS code:
Normally problems with this kind of loop stem from the fact that it isn't protecting against something being removed from a list during processing. I don't remember exactly where the trvch_wnext() thing comes from but it's likely a way to protect against bad data in the character list that goes beyond the normal checks in the snippet you posted.
It would be interesting to see if whatever you were doing can still cause a crash with the default FUSS distribution.
lc1 = trworld_create( TR_CHAR_WORLD_FORW ); for( ch = first_char; ch; ch = trvch_wnext( lc1 ) ) { set_cur_char( ch ); will_fall( ch, 0 ); if( char_died( ch ) ) continue;
Normally problems with this kind of loop stem from the fact that it isn't protecting against something being removed from a list during processing. I don't remember exactly where the trvch_wnext() thing comes from but it's likely a way to protect against bad data in the character list that goes beyond the normal checks in the snippet you posted.
It would be interesting to see if whatever you were doing can still cause a crash with the default FUSS distribution.
#5 Aug 30, 2024 8:22 pm
Conjurer
GroupMembers
Posts423
JoinedMar 7, 2005
In my case, I believe the issue was the character in question drowned. Subsequently, the char_check( ) call to will_fall( ) was trying to determine a down exit the the room ch was in, but of course that seg faulted since there wasn't any room and will_fall( ) was written assuming one would always exist for the caller, apparently.
My base is older and while patched up with every bug fix I ever found published, and then some, the trvch_wnext( ) thing is still on my to-do list. This may or may not have been an issue with it, might be difficult to test it out. Personally, I'm content to wrap the will_fall( ) between char_died( ) checks and be done with it for now.
Another good idea might be to make will_fall( ) gracefully return after logging an error, rather than crashing the MUD when there's no ch->in_room to speak of.
My base is older and while patched up with every bug fix I ever found published, and then some, the trvch_wnext( ) thing is still on my to-do list. This may or may not have been an issue with it, might be difficult to test it out. Personally, I'm content to wrap the will_fall( ) between char_died( ) checks and be done with it for now.
Another good idea might be to make will_fall( ) gracefully return after logging an error, rather than crashing the MUD when there's no ch->in_room to speak of.
#6 Aug 30, 2024 10:53 pm
Black Hand
GroupAdministrators
Posts3,690
JoinedJan 1, 2002
The problem is that will_fall() itself may not even be the issue. It could be one of the subsequent calls to other things it makes, the most obvious of which would be the extract_char() function. If ch happens to be an NPC, that could easily trigger a problem that's not easy to solve even with char_died() calls since char_died() requires a valid ch value.
#7 Aug 31, 2024 12:27 am
Last edited Aug 31, 2024 12:28 am by GatewaySysop
Conjurer
GroupMembers
Posts423
JoinedMar 7, 2005
To be clear, it wasn't the fall that killed them and they didn't drown in a room from which falling was possible either. In this instance, ch was not an NPC, and this is where the trace pointed. Am guessing after get_exit( ) complained in the log about a null room, whoever tried to access pexit after this is what caused this particular issue.
For context, was testing out a PC drowning after their mount drowned and left them in the drink. Mount died just fine, but when the PC drowned, that was the issue.
In any case, so far so good and haven't been able to reproduce the issue since the change.
For context, was testing out a PC drowning after their mount drowned and left them in the drink. Mount died just fine, but when the PC drowned, that was the issue.
bool will_fall( CHAR_DATA *ch, int fall ) { EXIT_DATA *pexit; pexit = get_exit( ch->in_room, DIR_DOWN );
In any case, so far so good and haven't been able to reproduce the issue since the change.
Pages:<< prev 1 next >>