set_pager_color crash???

Posted by Nicklfire on Mon 11 Oct 2004 06:51 PM — 21 posts, 69,103 views.

#0
Hi, i'm still really new to coding and whatnot. I've come across this crash that has drastically lost the playerbase. Everytime a player is destroyed/quits/idles out etc. and the next command executed uses "set_pager_color" it crashes with this backtrace. "do_who" "do_score" "do_pract" etc.

#0 0x400c64a1 in malloc_consolidate () from /lib/libc.so.6
#1 0x400c5d83 in _int_malloc () from /lib/libc.so.6
#2 0x400c578c in calloc () from /lib/libc.so.6
#3 0x08126e6f in write_to_pager (d=0x853aef0, txt=0x8194d3b "\e[0;36m", length=7) at color.c:1021
#4 0x08126dde in set_pager_color (AType=6, ch=0x853cdb8) at color.c:999
#5 0x080e7a51 in do_score (ch=0x853cdb8, argument=0xbfffed02 "") at player.c:123
#6 0x080c6a2f in interpret (ch=0x853cdb8, argument=0xbfffed02 "") at interp.c:737
#7 0x08096de2 in game_loop () at comm.c:682
#8 0x080966b4 in main (argc=2, argv=0xbffff120) at comm.c:329
#9 0x40063d06 in __libc_start_main () from /lib/libc.so.6

I've installed Samsons ansii color code. I even recently remade the codebase on another server, built it all back up, and still have this same problem. If anyone could possibly help me with this that would be awesome. Thanks.

USA #1
Could you show this function and show which line is the one given by GDB:
#3 0x08126e6f in write_to_pager (d=0x853aef0, txt=0x8194d3b "\e[0;36m", length=7) at color.c:1021

That looks like a good place to start since it's where the code leaves SMAUG and enters library functions.
#2
void write_to_pager( DESCRIPTOR_DATA *d, const char *txt, int length )
{
int pageroffset; /* Pager fix by thoric */

if( length <= 0 )
length = strlen( txt );

if( length == 0 )
return;

if( !d->pagebuf )
{
d->pagesize = MAX_STRING_LENGTH;
CREATE( d->pagebuf, char, d->pagesize );
}
if( !d->pagepoint )
{
d->pagepoint = d->pagebuf;
d->pagetop = 0;
d->pagecmd = '\0';
}
if( d->pagetop == 0 && !d->fcommand )
{
d->pagebuf[0] = '\n';
d->pagebuf[1] = '\r';
d->pagetop = 2;
}
pageroffset = d->pagepoint - d->pagebuf; /* pager
fix (goofup fixed 08/21/97) */
while( d->pagetop + length >= d->pagesize )
{
if( d->pagesize > 32000 )
{
bug( "%s", "Pager overflow. Ignoring.\n\r" );
d->pagetop = 0;
d->pagepoint = NULL;
DISPOSE( d->pagebuf );
d->pagesize = MAX_STRING_LENGTH;
return;
}
d->pagesize *= 2;
RECREATE( d->pagebuf, char, d->pagesize );
}
d->pagepoint = d->pagebuf + pageroffset; /* pager fix (goofup fixed 08/21/97) */
strncpy( d->pagebuf + d->pagetop, txt, length );
d->pagetop += length;
d->pagebuf[d->pagetop] = '\0';
return;
}
------------------
Thats the function and heres the line the backtrace points to.

CREATE( d->pagebuf, char, d->pagesize );


Thanks.

Amended on Mon 11 Oct 2004 08:01 PM by Nicklfire
USA #3
In the gdb backtrace, could you go to that frame and type:

print d
print d->pagebuf
print d->pagesize

and say what it prints out?
#4
(gdb) print d
$1 = (DESCRIPTOR_DATA *) 0x853aef0
(gdb) print d->pagebuf
$2 = 0x0
(gdb) print d->pagesize
$3 = 4096
(gdb)

I'm still super new to GDB but i think thats it o_0. Thanks.
USA #5
OK. Since that looks normal, and since the bug is in malloc_consolidate, my bet is that somewhere you are either:
a) freeing something twice
b) using free on a STRALLOCed string (instead of STRFREE), or using STRFREE on a malloced string (instead of free)

I would go through the stuff you added in the snippet and make sure you did it all correctly and exactly as specified. If that doesn't work, I would suggest uninstalling the snippet to see if the problem is somewhere else. And finally, I would suggest using a program such as Valgrind to hunt down the memory error.
#6
Ok well i was playing around with connect/destroy. I have 2 servers running, 1 with the leak i mentioned, the other is stock smaug with the ansii color snippet installed. When i destroy a player on the leaked one i get "Player Name destroyed. Pfile saved in backup directory. Then i "who" or "score" and it crashes. But on the new one with the same snippet installed exactly I get "Player does not exist." but it still destroys them. I type "who" after and it works fine. So now i'm starting to look into that freeing stuff. Just posted this incase it could help pinpoint the problem. Thanks.

Edit: I also came to the conclusion that it's not anything in destroy that's crashing it, because i had a player log on, save, quit. Typed "who" it crashed. Logged back on and destroyed the player while they were offline and it didn't crash. -sulks-
Amended on Mon 11 Oct 2004 09:29 PM by Nicklfire
USA #7
I would look at the code that gets rid of descriptors. Seems that something in there isn't working right at all - seems that every time somebody leaves one way or another (cleanly or abruptly) the game is put into an unstable state.
#8
Hrm.. I thought about that at first but I have 2 of the exact same codebases, all the one that crashes has different is things added to nanny for making a char. Such as ch->overdrive, ch->ap, ch->suppress. Added them to mud.h, save.c and that's about it. I haven't touched descriptors or anything :/ . Thanks again.
USA #9
Well, I would go look at those variables then and make sure that they are allocated and destroyed correctly (e.g. hashed string creation matches with hashed string deletion...)

Since the error is in malloc_consolidate, that implies that some pointer somewhere wasn't manipulated properly. If you have access to Valgrind I suggest you run it - it'll most likely be able to tell you exactly where the bad manipulation takes place. And maybe even some other bugs you didn't know about. :-)
#10
Thanks again for the help. Valgrind looks a bit complicating :/ . It's weird though. There will be the odd time where it doesn't crash for like.. 5-6 quits. And then one will. Even if there all after each other. (All these quits are just made chars btw, so there all the same)
USA #11
Valgrind is certainly daunting but then again you have a rather daunting problem. :-) Memory bugs like this are among the hardest to track down.

There's a way to turn on malloc debugging without valgrind, and it helps a bit but it's fairly complicated. Something about setting an environment variable (MALLOC_CHECK) to 2 and compiling your code with #define MALLOC_CHECK 2 as well. I think it's that. You could check the manpage for malloc, it might tell you more precisely what you need to do.

That turns on internal malloc-library debugging which will help spot double-frees or things like that.
Canada #12
With these snippets that you added, did any of them add/remove strings that are in char_data/pc_data? I would double check all those strings to make sure that:

1. If is allocated using STRALLOC, it is being freed with STRFREE, and that anything allocated with str_dup is being freed with DISPOSE

2. Check that your STRFREE/DISPOSE have checks in the macros in mud.h for null input.

3. Check that, like Ksilyan said, that your not double freeing your strings.

If you have valgrind installed, I would recommend that you use this:

valgrind -v --leak-check=yes --show-reachable=yes --gdb-attach=yes --num-callers=10 --logfile=valgrind ../src/smaug 4000 &

This should create log files from the output. You could then paste the output so otheres could look at them and help you out from them.
#13
The only snippets i've added are... hotboot and ansii color fix. And i added ch->overdrive, ch->ap, ch->suppress
ch->mod to the char_data structure. int, int, long int, float. I'll try that valgrind thing like you said when i first opened it i was like O_O what is this. :/ but yeah i'll post back when I can get it to work. Thanks guys :D

Edit: I checked my macros and it has the stuff for null, weirdly i have 2 macros for STRFREE that's probably not the problem considering both the leaking codebase and working one have 2.

Edit2: Ok I tried to install valgrind but it tries to install stuff into the servers folders and i don't have the permissions... so I guess thats outta the question x_x;.
Amended on Tue 12 Oct 2004 06:50 PM by Nicklfire
#14
Any idea as to why I created a character, did the EXACT same process everytime. Log on. 2 enters from the ansii screens. save, quit. First 4 times it didn't crash. Then the fifth did. -confused-
USA #15
Have you tried using the malloc debugging?

Also you should be able to install valgrind into your own directory; try --prefix="/home/myhomedir/" on the configure script (set your home dir appropriately.)
#16
All night last night i tried to find out how to malloc debug X_X someone told me i needed malloc.c so i searched and found nothing...

Edit: I noticed in comm.c MALLOC_DEBUG but i have no idea how to set that up..

Interesting enough... i kept recreating a char over and over and over and over till it crashed about on the seventh time without another command going through, crashed on the destroy. And the core file was different in a way. I'm pretty sure this is linked to the leak i'm dealing with.

#0 0x400c62e1 in _int_free () from /lib/libc.so.6
#1 0x400c50bf in free () from /lib/libc.so.6
#2 0x0809e58c in free_char (ch=0xf18) at db.c:2946
#3 0x080b81f7 in clean_char_queue () at handler.c:3581
#4 0x08114b47 in update_handler () at update.c:2077
#5 0x08093bf4 in game_loop () at comm.c:702
#6 0x08093494 in main (argc=2, argv=0xbfffe590) at comm.c:329
#7 0x40063d06 in __libc_start_main () from /lib/libc.so.6

(gdb) frame 2
#2 0x0809e58c in free_char (ch=0xf18) at db.c:2946
2946 DISPOSE( ch );



Amended on Tue 12 Oct 2004 11:24 PM by Nicklfire
USA #17
I'm almost positive at this point that something is being freed twice or you have mismatching hashed vs. unhashed allocation/deallocation.
Quote:
someone told me i needed malloc.c so i searched and found nothing...
Was that someone here? What I said is to look at the manpage for malloc, and then added the defines to your environment variables and your makefile so that it compiles in debug mode.

Where did you see MALLOC_DEBUG?
#18
The person that told me to get malloc.c was a friend from MSN but i don't think he knew what he was talking about o_0. As for MALLOC_DEBUG i see this in comm.c, but that's the only reference to malloc through the whole code. I read the manual for malloc in the shell and that stuff makes no sense to me -stupid- sorry x_x;. thanks.


/*
* Memory debugging if needed.
*/
#if defined(MALLOC_DEBUG)
malloc_debug( 2 );
#endif

~from comm.c ^^~
USA #19
Right. You need to edit your makefile to add a line defining MALLOC_DEBUG to 2. Or, you could edit mud.h and make the first line:
#define MALLOC_DEBUG 2
#20
Ok I added that line and I "make clean" then recompile, and i get this.

comm.o(.text+0x1f): In function `main':
/home/mud/dwd/smaug/src/comm.c:169: undefined reference to `malloc_debug'
comm.o(.text+0x6cd): In function `accept_new':
/home/mud/dwd/smaug/src/comm.c:522: undefined reference to `malloc_verify'

first error line:
/*
* Memory debugging if needed.
*/
#if defined(MALLOC_DEBUG)
malloc_debug( 2 );
#endif


second:
#if defined(MALLOC_DEBUG)
if ( malloc_verify( ) != 1 )
abort( );
#endif


I added
#define MALLOC_DEBUG 2
to mud.h and got those errors.. sorry I probably sound like the biggest moron in the world @_@. thanks.