Gdb didn't catch segfault?

Posted by Zeno on Sun 26 Mar 2006 05:19 AM — 32 posts, 115,691 views.

USA #0
So my Project CR seems to crash like once every 3 days. So I attached gdb to it and let it run. 3 days later, it crashes.
(gdb) c
Continuing.
Segmentation fault

(Between continue and segfault was 3 days)

Er. Why didn't it go into a backtrace? It also didn't dump a core.
Australia Forum Administrator #1
Did you compile with debugging enabled? See my post about gdb for details. Also ensure you remove the stuff inside SMAUG that catches segmentation faults (see the same post).

Before waiting 3 days, simulate a crash (make a command dereference nil or something) and check that you are catching it.
USA #2
Simulating a crash produces a core, I've tested that. This isn't Smaug by the way. Yes, my Makefile has -g3 in it.
USA #3
Could the segfault be in a thread or attached process, perhaps? It's possible that if it's not your process that's dying, gdb won't catch it properly. That being said, if it crashes enough to kill the program, it should crash enough to make gdb catch it...

Are you using threads/attached processes in the first place? You're using MySQL, right? Maybe it's an issue with that...
USA #4
This is the only process for it, but I do think it uses threads... Not that I have any idea what they are. Not using MySQL.
USA #5
If you are running from inside gdb, then it won't generate a backtrace upon a segfault, you need to tell it to do that afterward. You would still be within a live run of the game at that point.

Of course if the crash was bad enough to kill the debugger too, that's going to be difficult to track down unless you know how to make it happen.
USA #6
I should have been more specific. The debugger was no longer running, and I was back into bash.
USA #7
Try adding some simple log statements (or print statements and redirect the output) to the latest code additions. Print out the values of things. Chances are you have a corrupt pointer somewhere.
USA #8
I haven't added code to it in... months. Another note is that nothing happens on the MUD for those 3 days.
USA #9
If this started happening since the Arthmoor upgrades, I'd make sure that you recompiled [i]every single object file[/i] that you have to make sure that everything is linking against the proper libraries etc. It's possible that if you have old libraries, something ever so slightly incompatible exists in some obscure location.
USA #10
Nah, Project CR isn't on Arthmoor. It's on my own machine.
USA #11
Well, the same thing applies if you upgraded kernel, C runtime libraries, g++, anything... You never know. (Even if you're running under e.g. Cygwin)
USA #12
I haven't upgraded anything. Could you explain (or link to) details about threads? I'm pretty sure there was a mention of threads when I originally ran the exec with gdb which I've never seen.
USA #13
My understanding is that gdb doesn't behave very well with threads. I had several class projects that we had to debug the old-school, old-fashioned way by hand because gdb couldn't work with the threads. Apparently, if one thread crashes it doesn't always bring you to the thread that crashed, but it'll interrupt the "main thread", or something odd like that.

It's possible that it's just the version of gdb we were using, but I've heard from several people in several places that gdb doesn't behave too well. Unfortunately I don't have any articles or manuals lying around that would explain it.

It's just very strange that it doesn't seem to do anything at all. You say that when you run it without gdb, it doesn't crash?

Maybe what you could do is add log entries to all kinds of places all over the code, like when the update function is run etc. That might at least help track down what part of the code is dying -- that is getting closer to the old-fashioned way of debugging things. :-)
USA #14
Nah, it'll crash after ~3 days with or without gdb attached.

This is what I meant by seeing threads:

(gdb) run
Starting program: /home/zeno/chub/src/chub
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 26181)]


Now if I do Ctrl+C:

Program received signal SIGINT, Interrupt.
[Switching to Thread 16384 (LWP 26181)]
0x401723c2 in select () from /lib/libc.so.6


(gdb) bt
#0  0x401723c2 in select () from /lib/libc.so.6
#1  0x00000006 in ?? ()
#2  0x00000000 in ?? ()
#3  0xbffff710 in ?? ()
#4  0x0804953c in game_loop (control=0) at socket.c:227
#5  0x08049294 in main (argc=1, argv=0xbffff794) at socket.c:79


Continue:

(gdb) c
Continuing.
[New Thread 32769 (LWP 26183)]
[New Thread 16386 (LWP 26184)]
[Thread 16386 (LWP 26184) exited]
Amended on Tue 28 Mar 2006 02:01 AM by Zeno
USA #15
It looks like when you continue, a new thread is launched that wasn't there before, and it didn't stop the old one. Can't figure out why that would be, though.

What libraries are you linking with? Any idea what shared libraries it's loading on startup?
USA #16
What includes?
mud.h:#include <zlib.h>
mud.h:#include <pthread.h>
mud.h:#include <arpa/telnet.h>
mud.h:#include "random.h"
interpret.c:#include <sys/types.h>
interpret.c:#include <stdio.h>
interpret.c:#include <string.h>
interpret.c:#include <ctype.h>
interpret.c:#include <time.h>
interpret.c:#include <stdarg.h>


I think there's some more. pthread makes me wonder though.
Australia Forum Administrator #17
A crash that does not produce helpful information can often be caused by a badly corrupted stack. If the stack itself is wiped out, then doing a backtrace can be a problem.

Wiping the stack isn't that hard, overwriting a local variable can easily do it (that is, memset or strcpy into more space than was allocated).
USA #18
Nick's right about the local variables being smashed. Valgrind would help you with that.

As for pthread, it should be easy to find out where you're using it... just grep for 'pthread'. (And I actually meant what you're linking with at link time i.e. what -l flags you send to g++ at link phase.)
USA #19
socket.c:  pthread_attr_t       attr;
socket.c:  pthread_t            thread_lookup;
socket.c:  pthread_attr_init(&attr);
socket.c:  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
socket.c:      pthread_create(&thread_lookup, &attr, &lookup_address, (void*) lData);
socket.c:  pthread_exit(0);


L_FLAGS = -lz -lpthread -lcrypt
USA #20
OK, it looks like you create a thread called "thread_lookup"; I imagine you are using that to do the DNS lookups so that the whole MUD doesn't hang if the DNS is slow? That's something I've been meaning to do for a while.

Anyhow, have you observed any correlation at all between someone connecting and the MUD crashing a short time later?
USA #21
I can't find anything related to the crash besides for being ~3 days running and then it crashes.

Weird... hostnames? I've never seen that feature in SocketMUD. It just displays the IP as far as I've.
USA #22
It's weird that it's happening so regularly after 3 days. Any chance of an overflow somewhere on a timer?

As for hostnames: it's possible that the feature doesn't quite work. Or that you have to type 'users' to see the hostnames, because it's in the process of resolving them. But the point of the feature is to prevent the entire MUD from hanging if the DNS lookup hangs. Generally that happens if the DNS resolver is having issues.
USA #23
The %MEM is... 74.3. Cough. I should have looked at that earlier.

What I now plan to do is restart from the start. I have a lot more knowledge then I did when I started, and I could also work Lua into it.
USA #24
Maybe you have a memory leak that after 3 days is causing it to overflow the memory quota. Have you tried running Valgrind on it?
USA #25
The memory quota? I have this installed on my local machine. Is there really a memory quota included, or is it normally set by the admin? Because I haven't set it.
USA #26
Oh, right, I forgot that this was on your local machine, not a public server. So there shouldn't be a memory quota... sorry. :-)

Still, it's worth running this through Valgrind, if you can.
USA #27
*grunt*

(gdb) run
Starting program: /home/zeno/chub/src/chub
[Thread debugging using libthread_db enabled]
[New Thread 16384 (LWP 26217)]
[New Thread 32769 (LWP 26219)]
[New Thread 16386 (LWP 26220)]
[Thread 16386 (LWP 26220) exited]
Cannot find user-level thread for LWP 26217: generic error
(gdb)


Between "exited" line and "Cannot find user-level" line is 3 days; 27th to 31st.
Amended on Fri 31 Mar 2006 10:38 AM by Zeno
USA #28
You know, this might just be a bug in gdb... have you tried upgrading to the latest version?
USA #29
GNU gdb 6.3


I guess 6.4 is the newest version. Maybe I'll upgrade...
USA #30
Let me know if this fixes anything. I have to admit that I'm stumped on this one...
USA #31
Definitely looks like time for "old school" debugging. Lots of log messages sprinkled about. Start general. Log message at the beginning of game_loop, in between the descriptor input and the descriptor output, beginning and end of the update_handler, and the end of game_loop. Then when it just up and dies, if you haven't killed the thing with 3 days worth of log spam, you can begin to narrow down the search with log messages in more specific parts. Pain in the ass, but some bugs just demand this kind of attention.