|
Funny Networking Crashes |
X-G
Member #856
December 2000
|
This rather weird bug has been coming up a lot lately, and I'm doing my best to battle it. How it arises, though, is outside of my understanding. Perhaps someone here can see it. I'm getting some really funny results and crashes in my networking code. I've thrown in a lot of TRACE() calls everywhere in the code to keep on top of things, and some damn funny results pop out. Here's a log entry: Quote: Attempting to start server ... This is the whole log. It freezes or segfaults after this. Those of you experienced with network programming might immedeately see that the highlighted line is weird. It might take some explanation of exactly what is being pushed here, though. My system is laid out like this: A listening CSocket will, when it encounters an incoming connection, accept that socket using normal socket operations, wrap it up in another CSocket, and push it onto an internal STL list, to be retreived by the main program later. Mutexes are being employed to ensure the two different threads don't interfere with each other.
Now, as you can see, SOMEHOW this function's socket is set to -1, which is obviously an invalid socket descriptor. Then, it somehow accepts and pushes ITSELF onto its own stack of incoming connections. Finally, the prog crashes. -- |
Thomas Fjellstrom
Member #476
June 2000
|
(IMO) Sounds to me like you may be having problems with out of bounds memory access. (ie: accessing invalid pointers..) -- |
X-G
Member #856
December 2000
|
What I'd particularly like to know is how a pointer just retrieved from new can be set to this ... (surely, it can't be the other way around here, can it?) If it helps, I'll post the socket wrapping function and associated helper ...
The two queues are STL lists (list<CMessage> ). CMessage is a class of my own (yes, it has copy constructors and overloaded = operator). http://www.gamleby.net/x-g/edit.gif After some more searching, it seems that select() returns -1, which would be an error. Still, the socket is in the incoming set, and errno is 0. This is getting worse every minute. http://www.gamleby.net/x-g/edit.gif Great, now it segfaults in THIS function, too. It's the line with "CSocket *s = ..." ... and begin() must be a proper iterator after checking that the list isn't empty, right? CSocket *CSocket::PopConnection() { if (sock_queue.empty()) return NULL; CSocket *s = *(sock_queue.begin()); sock_queue.pop_front(); return s; }
-- |
Elias
Member #358
May 2000
|
CSocket::CSocket(SOCKET s) { CSocket(); if (!s) return; sock = s; state = SST_CONNECTED; ResetQueues(); } I don't know much C++ so may be totally off, but what effect should the line "CSocket();" have? To my understanding, it will create another CSocket object, which is never referenced (unless they made C++ do it the same way as Java by now I think you can't directly call a constructor like that - but as I said, I may be wrong. Quote:
-- I just stop by on allegro.cc like twice a week, so I would have missed it - is there any thread explaining your sig? Looks like just some random german words to me.. -- |
gnolam
Member #2,030
March 2002
|
I can fill you in on the sig thing: X-G said SciTE für alle!, which made Spellcaster reply "Nur aus Neugierde: Seit wann ist Deutsch hier so beliebt?". Just for fun, I therefore changed my sig to "An, auf, hinter, in, neben, über, unter, vor, zwischen" (prepositions that control the accusative and dative cases in German). X-G changed his sig to match mine (but with the prepositions that control the accusative), and now Trumgottist completed the cycle with "Aus, ausser, bei, ..." (dative) -- |
Elias
Member #358
May 2000
|
Heh, I see.. I speak German, but I'd have had no idea you can group prepositions like that -- -- |
Evert
Member #794
November 2000
|
And as I said earlier, what I remember from highschool is bis, dürch, für, gegen, ohne, um, so I'm left with the feeling that X-G's sig is incomplete... |
Elias
Member #358
May 2000
|
Hm, is "bis" a preposition at all? It means "until", so you can only put a time/location after it. And I just realized, there's a lot more prepositions with genitive than the 2 i came up with - that's probably why you only had to learn dativ/accusativ ones About the first topic, I just tried out what happens if I call a constructor from another constructor, and my suspection was right: It creates another object, and it has no relevance if you call it from within a constructor, or somewhere else. If you want multiple constructors of a class to share the same initalization code, you have to make a separate initialization method in C++, and call it from all the constructors. -- |
Sakuera
Member #3,222
February 2003
|
Hmm, I almost fail German exams, cause e.g. I translate "What's your name" to "Was ist dein nehme" despite I know it should be "Wie heisst du". |
Elias
Member #358
May 2000
|
"Was ist dein Name" is correct. It just sounds a bit more formal, probably like if you say "How are you named?" in English. -- |
spellcaster
Member #1,493
September 2001
|
Nope. It should be "Wie ist Dein Name?" -- |
Evert
Member #794
November 2000
|
Shouldn't that more properly be `Wie heissen Sie' and `Wie ist Ihre Name?' I recently pulled my French grammer book off the shelf... perhaps I should do the same with German... |
Elias
Member #358
May 2000
|
Blah, I can't even speak my mother tongue. It's of course "Wie", not "Was". But still, "Was war nochmal dein Name?" wouldn't necessarily sound wrong to me.. About using "Sie" and "Ihr" instead of "du" and "dein" (before the latest Rechtschreibreform, the latter also started with capitals).. it's the same as in French. -- |
Thomas Fjellstrom
Member #476
June 2000
|
Bah. Its all greek to me. -- |
Frank Drebin
Member #2,987
December 2002
|
It should be "Wie heisst du?" or "Wie ist dein Name?" oder wie oder was scheisse net nochmal. |
X-G
Member #856
December 2000
|
Elias: You are correct - but I don't think it's that important - the default constructor does almost nothing. now can we stop being off-topic? http://www.gamleby.net/x-g/edit.gif What the hell is going on here? Take a look at this little piece of code. It's from the function that's supposed to check for incoming stuff. Major paranoid debugging stuff there. Now, you would expect sock to stay the same, right? Those traces are overly paranoid, right? Wrong. allegro.log said: Connecting to 127.0.0.1:26078 ...
-- |
CGamesPlay
Member #2,559
July 2002
|
Just some crazy, off-the wall idea, maybe your CSocket instance that was listening also sent out the request? Yeah, I didn't think that was it... -- Ryan Patterson - <http://cgamesplay.com/> |
Thomas Fjellstrom
Member #476
June 2000
|
Um.. variables changing on thier own... What does that remind me of... Hmmm.. Memory/buffer overruns? accessing invalid pointers maybe? something like that. Scour your source code. You're bound to find a little error somewhere. (It seems my network code doesn't have problems like that.. It sucessfully serves webpages for me.. but then I don't directly use select... Its all even threaded...) -- |
X-G
Member #856
December 2000
|
I may have found what could be wrong. I'm not entirely sure yet. You know all those TRACE() things I put in everywhere, for debugging? Well ... Allegro isn't thread-safe, as you know. And the trace printing thing isn't mutexed. And my prog is multi-threaded. Could that have something to do with it? -- |
Elias
Member #358
May 2000
|
You could try replacing it with printf and see if you get any difference. Do you also get the same results when there's only one thread listening for connections? And maybe you could show the rest of the incoming function, and where it is called from, there's always the possibility of a small hidden bug somewhere in the code, even it is very trivial code Btw, under which OS is this running? gdb (and probably the MSVC-debugger) should allow to analyze variables in different threads after a crash (or at a breakpoint) - i don't know how good gdb is with C++ though. And I heared, in linux, linking with electricfence allows to detect memory leaks or even buffer overruns. I have no idea if it works with STL, but it might be worth a try. -- |
X-G
Member #856
December 2000
|
I tried to remove -DDEBUGMODE, which turns all TRACE()'s into nothing. It still crashes, but somewhere else this time. Anyway, I use Dr MinGW for debugging at the moment, and sadly it doesn't seem to be able to watch values. Gdb is a pain, because each TRACE() seems to send a SIGTRAP to the program, causing gdb to keep breaking execution. The program only has two threads; the main thread, and the thread with the listening socket. -- |
Elias
Member #358
May 2000
|
Hm, yes, I remember that behaviour of TRACE and switched to printf because of it. And gdb really is much nicer in linux. Try compiling in linux, and look at the stack backtraces you get there for both threads - it might reveal something. I also have another guess where things could go wrong - maybe when you remove items from the STL list. Even if you are locking that part of the code, it sounds suspicious of having the capability to screw up memory -- |
X-G
Member #856
December 2000
|
My project doesn't compile in linux yet, and I don't intend to make any conscious effort towards it until I get this working on Windows to begin with. -- |
Cage
Member #1,277
March 2001
|
X-G: C or C++? If C++, you could use this function that I've written instead of TRACE()... void debugInfo(const char *format, ...) { char buf[512]; va_list ap; va_start(ap, format); uvszprintf(buf, sizeof(buf), format, ap); va_end(ap); ofstream messageOut("debugInfo.txt", ios::app); messageOut << buf << "\n"; messageOut << flush; messageOut.close(); } If C, you could probably change the file part a bit to use C-style I/O . Just make sure you delete debugInfo.txt upon startup every time .
----- |
X-G
Member #856
December 2000
|
Cage: You'd think the fact that all the code snippets involve classes would tip you off as to what I'm using, eh? Thanks, anyway. I'll try it out. Gdb is being a bitch right now, though - it refuses to run my project and starts spewing lines mentioning coffread.c. -- |
|