Welcome to the Builder Academy

Question Crashes - It is to pull out the hair, it is.

More
05 Nov 2026 18:57 #11068 by krell
Some crash logs captured in script() on gdb() and tt++(). Nothing the PC does seems to trigger it, it rather random and just happens after varying lengths of time.

As I was running this one as a user I don't have a syslog.CRASH file to share for this particular instance. I can provide a syslog.CRASH from the main instance running as its own daemon. Noticeably, the differences in value of what's being freed and what I believe if the PID of the running circle, yet remarkably similar at the same time
Code:
Nov 05 17:11:08 2026 :: nusage: 1   sockets connected, 1   sockets playing circle(2851) in free(): write to free mem 0x7d5d39a0380[56..63]@112
 

Snips from the gdb() side of the screen captures.
Code:
circle(76783) in free(): write to free mem 0x7c531a2dbd0[56..63]@112 Program received signal SIGABRT, Aborted. thrkill () at /tmp/-:2 2       /tmp/-: No such file or directory.         in /tmp/- Current language:  auto; currently asm (gdb) bt #0  thrkill () at /tmp/-:2 #1  0x96d145f72d5efb2b in ?? () #2  0x000007c512fcde9b in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51 #3  0x000007c512f899b4 in wrterror (d=Variable "d" is not available. ) at /usr/src/lib/libc/stdlib/malloc.c:378 #4  0x000007c512f8b4f3 in ofree (argpool=0x7aa804cb3f90, p=Variable "p" is not available. ) at /usr/src/lib/libc/stdlib/malloc.c:782 #5  0x000007c512f8ac33 in _libc_free (ptr=0x7c506e7c010) at /usr/src/lib/libc/stdlib/malloc.c:1735 #6  0x000007c2c9921890 in free_var_el (var=0x7c5049cf300) at dg_handler.c:31 #7  0x000007c2c9921919 in free_varlist (vd=0x7c5049cf300) at dg_handler.c:45 #8  0x000007c2c99364b7 in script_driver_default (go_adress=0x7aa804cb45b0, trig=0x7c59ccf70e0, type=0, mode=0, default_ret=1)     at dg_scripts.c:2815 #9  0x000007c2c9935510 in script_driver (go_adress=0x7aa804cb45b0, trig=0x7c59ccf70e0, type=0, mode=0) at dg_scripts.c:2580 #10 0x000007c2c993ca65 in greet_mtrigger (actor=0x7c54e3b0250, dir=1) at dg_triggers.c:227 #11 0x000007c2c98a5599 in do_simple_move (ch=0x7c54e3b0250, dir=1, need_specials_check=1) at act.movement.c:322 #12 0x000007c2c98a5c23 in perform_move (ch=0x7c54e3b0250, dir=1, need_specials_check=1) at act.movement.c:358 #13 0x000007c2c999e7e0 in mobile_activity () at mobact.c:107 #14 0x000007c2c990695c in heartbeat (heart_pulse=18000) at comm.c:1069 #15 0x000007c2c9903dbc in game_loop (local_mother_desc=6) at comm.c:1023 #16 0x000007c2c99021ba in init_game (local_port=8000) at comm.c:573 #17 0x000007c2c9901f1e in main (argc=2, argv=0x7aa804cb56f8) at comm.c:350 (gdb) up #1  0x96d145f72d5efb2b in ?? () (gdb) up #2  0x000007c512fcde9b in _libc_abort () at /usr/src/lib/libc/stdlib/abort.c:51 51      /usr/src/lib/libc/stdlib/abort.c: No such file or directory.         in /usr/src/lib/libc/stdlib/abort.c Current language:  auto; currently minimal (gdb) up #3  0x000007c512f899b4 in wrterror (d=Variable "d" is not available. ) at /usr/src/lib/libc/stdlib/malloc.c:378 378     /usr/src/lib/libc/stdlib/malloc.c: No such file or directory.         in /usr/src/lib/libc/stdlib/malloc.c (gdb) up #4  0x000007c512f8b4f3 in ofree (argpool=0x7aa804cb3f90, p=Variable "p" is not available. ) at /usr/src/lib/libc/stdlib/malloc.c:782 782     in /usr/src/lib/libc/stdlib/malloc.c (gdb) up #5  0x000007c512f8ac33 in _libc_free (ptr=0x7c506e7c010) at /usr/src/lib/libc/stdlib/malloc.c:1735 1735    in /usr/src/lib/libc/stdlib/malloc.c (gdb) up #6  0x000007c2c9921890 in free_var_el (var=0x7c5049cf300) at dg_handler.c:31 31          free(var->name); (gdb) list 26      27      /* frees memory associated with var */ 28      void free_var_el(struct trig_var_data *var) 29      { 30        if (var->name) 31          free(var->name); 32        if (var->value) 33          free(var->value); 34        free(var); 35      } (gdb) print var $1 = (struct trig_var_data *) 0x7c5049cf300 (gdb) print var->name $2 = 0x7c506e7c010 "actor" (gdb) info local No locals. (gdb) up #7  0x000007c2c9921919 in free_varlist (vd=0x7c5049cf300) at dg_handler.c:45 45              free_var_el(j); (gdb) info local i = (struct trig_var_data *) 0x7c559ef8700 j = (struct trig_var_data *) 0x7c5049cf300 (gdb) list 40          struct trig_var_data *i, *j; 41      42          for (i = vd; i;) { 43              j = i; 44              i = i->next; 45              free_var_el(j); 46          } 47      } 48      49      /* Remove var name from var_list. Returns 1 if found, else 0. */ (gdb) up #8  0x000007c2c99364b7 in script_driver_default (go_adress=0x7aa804cb45b0, trig=0x7c59ccf70e0, type=0, mode=0, default_ret=1)     at dg_scripts.c:2815 2815      free_varlist(GET_TRIG_VARS(trig)); (gdb) info local depth = 1 ret_val = 1 cl = (struct cmdlist_element *) 0x0 cmd = 0x7aa804cb40f0 "mforce  }10000244 flee" p = 0x7c5c6df5562 "end" sc = (struct script_data *) 0x7c5140d1db0 temp = (struct cmdlist_element *) 0x7ffffff600000000 go = (void *) 0x7c4dd6f06f0 (gdb) list 2810        case MOB_TRIGGER:    sc = SCRIPT((char_data *) go);           break; 2811        case OBJ_TRIGGER:    sc = SCRIPT((obj_data *) go);            break; 2812        case WLD_TRIGGER:    sc = SCRIPT((room_data *) go);    break; 2813      } 2814      if (sc) 2815      free_varlist(GET_TRIG_VARS(trig)); 2816      GET_TRIG_VARS(trig) = NULL; 2817      GET_TRIG_DEPTH(trig) = 0; 2818    2819      depth--; (gdb) up #9  0x000007c2c9935510 in script_driver (go_adress=0x7aa804cb45b0, trig=0x7c59ccf70e0, type=0, mode=0) at dg_scripts.c:2580 2580      return script_driver_default(go_adress, trig, type, mode, 1); (gdb) info local No locals. (gdb) list 2575     * int mode 2576         TRIG_NEW     just started from dg_triggers.c 2577         TRIG_RESTART restarted after a 'wait' */ 2578    int script_driver(void *go_adress, trig_data *trig, int type, int mode) 2579    { 2580      return script_driver_default(go_adress, trig, type, mode, 1); 2581    } 2582    2583    int script_driver_default(void *go_adress, trig_data *trig, int type, int mode, 2584                             int default_ret) (gdb) up #10 0x000007c2c993ca65 in greet_mtrigger (actor=0x7c54e3b0250, dir=1) at dg_triggers.c:227 227             intermediate = script_driver(&ch, t, MOB_TRIGGER, TRIG_NEW); (gdb) info local t = (trig_data *) 0x7c59ccf70e0 ch = (char_data *) 0x7c4dd6f06f0 buf = 0x7aa804cb43b0 "}10000244"


Snippets from tintin++
Code:
500H 100M 82V > The Peacekeeper leaves east. 500H 100M 82V > The green gelatinous blob has arrived. 500H 100M 82V > The green gelatinous blob leaves east. 500H 100M 82V > The green gelatinous blob has arrived. 500H 100M 82V > The green gelatinous blob leaves east. 500H 100M 82V > The janitor has arrived. 500H 100M 82V > The janitor leaves west. 500H 100M 82V > The green gelatinous blob has arrived. 500H 100M 82V > The green gelatinous blob leaves south. 500H 100M 82V > The janitor has arrived. 500H 100M 82V > The janitor leaves east. The green gelatinous blob has arrived. 500H 100M 82V > The green gelatinous blob leaves south. 500H 100M 82V > The janitor has arrived. 500H 100M 82V > The green gelatinous blob has arrived. 500H 100M 82V > The janitor leaves south. 500H 100M 82V > The janitor has arrived. The green gelatinous blob leaves south. 500H 100M 82V > The janitor leaves south. 500H 100M 82V > The janitor has arrived. 500H 100M 82V > The janitor leaves east. 500H 100M 82V > ESC[0m#SESSION 'Clockwerx' DIED.ESC[0m ESC=ESC[?1049lESC[?7787lESC[r^MESC[69;1HESC[0m#SESSION 'gts' ACTIVATED.ESC[0m

Further notes.
System: OpenBSD 8.0
Platform: amd64
sysctl: vm.malloc_conf=SF
Compilation flags = -g -O0 -Wall -Wextra -Wpedantic -Wsystem-headers -Wno-error=gnu-include-next -Wstack-protector -fstack-protector-strong -Werror -Wno-error=unused-parameter -Wno-unused-parameter -ftrapv
CC = clang-22

Booting over to Debian and will try running a copy of the mud over there and see what happens.
Attachments:

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

More
06 Nov 2026 01:49 - 06 Nov 2026 02:07 #11072 by krell
In free_var_el() of dg_handler.c I changed
Code:
void free_var_el(struct trig_var_data *var) {   if (var->name)   free(var->name);    if (var->value)      free(var->value);    free(var);  }

to
Code:
void free_var_el(struct trig_var_data *var) {   if (var->name)   free(var->name);    if (var->value)      free(var->value);    free(var);    var = NULL;  }

recompiled and ran it. It ran for almost 40 minutes without crashing and I shut it down. Normally it would be under 20 minutes for a crash. Not conclusive, but something to go on?

That might be enough on its own, if that's the solution. Wondering if I should also nullify var->name and var->value after freeing them. Anyhow, I've made the changes, am recompiling and will see if this instance will run overnight.
Last edit: 06 Nov 2026 02:07 by krell.

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

More
06 Nov 2026 03:05 - 06 Nov 2026 13:25 #11073 by krell
NVM, red-herring. Is it var->name being freed somewhere else and then it gets passed to free_var_el()? Need to sleep on this one, I think.

** Following morning **

Okay, the only way I'm getting this done is to keep the debugger open and change things in the other windows where I think frees are happening but not being nulled. Leaning a lot on the compiler to correct me when I make bad assumptions about what can be nulled after free, but I seem to be making progress as I find myself being kicked further up the chain every time it crashes. This might be a while.
Last edit: 06 Nov 2026 13:25 by krell.

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

More
06 Nov 2026 23:31 #11074 by thomas
I think you're right, it's almost certainly a double free. But setting the variable to NULL in the function won't help. I've just checked the code and the var should be nulled everywhere, like it is here:
Code:
free_varlist(live_trig->var_list); live_trig->var_list=NULL;

I suggest you try running with MEMORY_DEBUG turned on.
The following user(s) said Thank You: krell

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

More
Yesterday 13:18 - Yesterday 17:10 #11076 by krell
I actually had just compiled with the MALLOC_DEBUG and ran the mud. It's been up almost an hour with no crash. A fluke? Possibly. I had also removed a lot of the other compilation flags, mostly because I ran ./configure from the mud's root and lost them. I think I'll kill the instance recompile with some of those flags set as well, probably only turning off warnings for GNU-extensions.

Addendum:
I think I'll compile with -Wno-error-unused-parameter and -Wno-error=unused-parameter for now. See attached file for details.

File Attachment:

File Name: unused-params.tar.gz
File Size:1 KB


Addendum 2:
zmalloc.log recorded a freed null in interpreter.c on line 467
Code:
467 free(cmd_sort_info); 468 CREATE(cmd_sort_info, int, num_of_cmds);


proposal: a guard statement?
Code:
467  if (!cmd_sort_info) 468    CREATE(cmd_sort_info, int, num_of_cmds); 469  else { 470    free(cmd_sort_info); 471    CREATE(cmd_sort_info, int, num_of_cmds); 472  }

zmalloc.log

zfree: ERR: Null pointer free'd: interpreter.c:467.


Checking leaks

zmalloc: UNfreed memory 0x0xa7ff543e844 48 bytes mallocd at lists.c:33
    00000000 00000000 00000000 00000000    ................
    00000000 00000000 00000000 00000000    ................

zmalloc: 1 leaks totalling 48 bytes... close, but not there yet

Last edit: Yesterday 17:10 by krell.

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

More
Yesterday 19:31 - Yesterday 19:33 #11077 by krell
Continued use of MALLOC_DEBUG since implementing the, possibly wrong, guard statement I only get the following:

$ cat zmalloc.log


Checking leaks

zmalloc: UNfreed memory 0x0x134f2a05744 48 bytes mallocd at lists.c:33
    00000000 00000000 00000000 00000000    ................
    00000000 00000000 00000000 00000000    ................

zmalloc: 1 leaks totalling 48 bytes... close, but not there yet.


I've been learning to use OpenBSD ktrace and kdump options as well on the other tbaMUD build I have on this machine. So far, I've been able to get the following output when it died, just the tail 20 lines, and I admit that I'm still learning out to use these tools effectively.

$ kdump | tail -n 20
77428 circle  CALL  getpid()
77428 circle  RET  getpid 77428/0x12e74
77428 circle  CALL  write(2,0x73de313e7110,0x19)
77428 circle  GIO  fd 2 wrote 25 bytes
      "circle(77428) in free(): "
77428 circle  RET  write 25/0x19
77428 circle  CALL  write(2,0x73de313e71f0,0x2b)
77428 circle  GIO  fd 2 wrote 43 bytes
      "write to free mem 0xcb07ae8fd20[56..63]@112"
77428 circle  RET  write 43/0x2b
77428 circle  CALL  write(2,0x73de313e7110,0x1)
77428 circle  GIO  fd 2 wrote 1 bytes
      "
      "
77428 circle  RET  write 1
77428 circle  CALL  sigprocmask(SIG_SETMASK,~0x20<SIGABRT>)
77428 circle  RET  sigprocmask 0<>
77428 circle  CALL  thrkill(0,SIGABRT,0)
77428 circle  PSIG  SIGABRT SIG_DFL
77428 circle  NAMI  "circle.core"

Last edit: Yesterday 19:33 by krell.

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

Time to create page: 0.452 seconds