Wierd crash - Need help to locate the problem from this GDB info

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago - 5 years 5 months ago #7878 by JTP
(gdb) up
#1  0x002e1b10 in raise () from /lib/libc.so.6
(gdb) up
#2  0x002e3421 in abort () from /lib/libc.so.6
(gdb) up
#3  0x080f30dd in char_from_room (ch=0xa82bc30) at handler.c:395
395         abort();
(gdb) up
#4  0x080ca48d in do_mteleport (ch=0xa6c66d8, argument=0xbf89b7ad "  }722 2311", cmd=0, subcmd=0) at dg_mobcmd.c:615
615           char_from_room(vict);
(gdb) up
#5  0x08105246 in script_command_interpreter (ch=0xa6c66d8, arg=0xbf89b7a4 "mteleport  }722 2311") at interpreter.c:510
510       ((*mob_script_commands[i].command_pointer) (ch, line, 0,
(gdb) up
#6  0x080d604c in script_driver (go_adress=0xbf89ba68, trig=0xa6c68b0, type=0, mode=1) at dg_scripts.c:2670
2670                if (!script_command_interpreter((char_data *) go, cmd))
(gdb) up
#7  0x080d6152 in trig_wait_event (event_obj=0xad84b70) at dg_scripts.c:757
757       script_driver(&go, trig, type, TRIG_RESTART);
(gdb) up
#8  0x080c827a in event_process () at dg_event.c:126
126         if ((new_time = (the_event->func)(the_event->event_obj)) > 0)
(gdb) up
#9  0x080b6531 in heartbeat (heart_pulse=393536) at comm.c:974
974       event_process();
(gdb) up
#10 0x080b98c8 in game_loop (local_mother_desc=3) at comm.c:941
941           heartbeat(++pulse);
(gdb) up
#11 0x080bb487 in init_game (argc=Cannot access memory at address 0x46a
) at comm.c:536
536       game_loop(mother_desc);
(gdb) up
#12 main (argc=Cannot access memory at address 0x46a
) at comm.c:356
356         init_game(port);


What is happening ?

After reboot this was in file error from the time of the crash:
Apr 6 12:55:06 :: SYSERR: NULL character or NOWHERE in handler.c, char_from_room
Last edit: 5 years 5 months ago by JTP.

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7879 by thomas
You can see it was "%teleport% %actor% 2311" that triggered it. (or vict instead of actor, or something)

And indeed - there is a check to make sure the game is in a consistent state when calling char_from_room():
/* move a player out of a room */
void char_from_room(struct char_data *ch)
{
  struct char_data *temp;

  if (ch == NULL || IN_ROOM(ch) == NOWHERE) {
    log("SYSERR: NULL character or NOWHERE in %s, char_from_room", __FILE__);
    exit(1);
  }

...
We can see that ch wasn't null (it was ch=0xa82bc30).

So, whoever is being teleported was in NOWHERE when they were moved from the room.

This might happen if they just died, I think.

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago #7880 by JTP
Usually that trigger has worked just fine...Any Way to prevent this from happening, so people can't be nowhere ?

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago #7881 by JTP
Have had alot of teleport crashes 1+ years ago. Even went away from them for awhile.

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7882 by thomas
Would you be willing to show us the trigger in question? There's really not a lot we can do to help you without it.

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago #7883 by JTP
sure
Trigger Intended Assignment: Mobiles
Trigger Type: Greet-All , Numeric Arg: 100, Arg list: None
Commands:
if %actor.class% != Thief
  wait 1 sec
  %send% %actor% %self.name% ...
  %echoaround% %actor% %self.name% ... %actor.name% ...
  wait 1 sec
  %asound% %actor.name% ...
  %teleport% %actor% 2311
  %force% %actor% look
else
  wait 1 sec
  emote ...
  say bla bla
end

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago - 5 years 5 months ago #7884 by thomas
Yes, there's the problem. And yes, we should be able to fix it.

At least I can extrapolate on how it fails.
Assume char X enters the room
X is not a thief, so he triggers the first if
The trigger waits a sec
... sends something to X
... and X's room
X quits (or rents out, or dies). X is now not in a room. But X is still online, so the trigger isn't stopped.
The trigger sends something to the room
... and attempts to move X
This fails, because X no longer is in the game (but at the menu, doing whatever).

So, how to fix this?
Either,
1) in the action functions (%force%, %teleport%, etc), checking if the player is in game before performing an action on them, or
2) when waking after waitstates, check that the player is actually a valid target

It turns out we have 1) in place in most such functions, but miss it in do_mteleport github.com/tbamud/tbamud/blob/master/src/dg_mobcmd.c#L624 :
  } else {
    if (*arg1 == UID_CHAR) {
      if (!(vict = get_char(arg1))) {
        mob_log(ch, "mteleport: victim (%s) does not exist",arg1);
        return;
      }
    } else if (!(vict = get_char_vis(ch, arg1, NULL, FIND_CHAR_WORLD))) {
      mob_log(ch, "mteleport: victim (%s) does not exist",arg1);
      return;
    }

-    if (valid_dg_target(ch, DG_ALLOW_GODS)) {
+    if (valid_dg_target(vict, DG_ALLOW_GODS)) {
      char_from_room(vict);
      char_to_room(vict, target);
      enter_wtrigger(&world[IN_ROOM(ch)], ch, -1);
    }
  }
}
Last edit: 5 years 5 months ago by thomas. Reason: better fix

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago #7885 by JTP
So with:
- if (valid_dg_target(ch, DG_ALLOW_GODS)) {
+ if (valid_dg_target(vict, DG_ALLOW_GODS)) {

Below isnt needed after all ?


+ if (IN_ROOM(vict) == NOWHERE)
+ return;
+

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7886 by thomas
correct. realized it immediately after pushing submit :S

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago - 5 years 5 months ago #7887 by JTP
enter_wtrigger(&world[IN_ROOM(ch)], ch, -1);

That is still ch and ch or should also be vict ?
Last edit: 5 years 5 months ago by JTP.

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7888 by thomas
Indeed, that should be vict also.

We're triggering an enter trigger in the new room we just sent vict to.

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago #7889 by JTP
So the all option already had:
if (valid_dg_target(vict, DG_ALLOW_GODS)) {
char_from_room(vict);
char_to_room(vict, target);
enter_wtrigger(&world[IN_ROOM(ch)], ch, -1); <<<---but still ch and ch here.

And the else if:
if (valid_dg_target(ch, DG_ALLOW_GODS)) {
char_from_room(vict);
char_to_room(vict, target);
enter_wtrigger(&world[IN_ROOM(ch)], ch, -1);


Alittle confusing...is the all part corrent then ?

  if (!str_cmp(arg1, "all")) {
    if (target == IN_ROOM(ch)) {
      mob_log(ch, "mteleport all target is itself");
      return;
    }

    for (vict = world[IN_ROOM(ch)].people; vict; vict = next_ch) {
      next_ch = vict->next_in_room;

      if (valid_dg_target(vict, DG_ALLOW_GODS)) {
        char_from_room(vict);
        char_to_room(vict, target);
        enter_wtrigger(&world[IN_ROOM(ch)], ch, -1);
      }
    }
  } else {
    if (*arg1 == UID_CHAR) {
      if (!(vict = get_char(arg1))) {
        mob_log(ch, "mteleport: victim (%s) does not exist",arg1);
        return;
      }
    } else if (!(vict = get_char_vis(ch, arg1, NULL, FIND_CHAR_WORLD))) {
      mob_log(ch, "mteleport: victim (%s) does not exist",arg1);
      return;
    }

    if (valid_dg_target(ch, DG_ALLOW_GODS)) {
      char_from_room(vict);
      char_to_room(vict, target);
      enter_wtrigger(&world[IN_ROOM(ch)], ch, -1);
    }
  }
}

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7890 by thomas
Yes, just created a pull request for that, too:

github.com/tbamud/tbamud/pull/48/commits...5a8d86178dd23287c789

I also double-checked that oteleport and wteleport are correct. This is a long-standing bug. Nice that you could help make it go away :)
The following user(s) said Thank You: lacrc

Please Log in or Create an account to join the conversation.

  • JTP
  • Topic Author
  • Offline
  • Platinum Member
  • Platinum Member
More
5 years 5 months ago #7891 by JTP
My pleasure, bug hunter :)

Im best at finding bugs, not so good at fixing them :


So was oteleport and wteleport ok ?

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7894 by Parnassus
Is it possible that the code is going wrong because of the way the trigger is written? I think I'd have written it like this:
Trigger Intended Assignment: Mobiles
Trigger Type: Greet-All , Numeric Arg: 100, Arg list: None
Commands:
+ wait 1 sec
 if %actor.class% != Thief
-   wait 1 sec
   %send% %actor% %self.name% ...
   %echoaround% %actor% %self.name% ... %actor.name% ...
-   wait 1 sec
   %asound% %actor.name% ...
   %teleport% %actor% 2311
+  wait 1 sec
   %force% %actor% look
 else
-  wait 1 sec
   emote ...
   say bla bla
 end

This gives much less time for movement although it's still possible. If this works, it might explain why the teleport crashes seem so random. My way would crash infrequently, the original way would crash sometimes, and it would never always crash.

Of course, finding the reason and fixing it beats lucky or unlucky triggers any time :)

Please Log in or Create an account to join the conversation.

More
5 years 5 months ago #7896 by thomas
No, not really. In practice, you'd still have the first wait giving the player a chance to log off.

The fix will make sure it works both ways, though :)

Please Log in or Create an account to join the conversation.

Time to create page: 0.180 seconds