View previous topic :: View next topic |
Author |
Message |
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Sat Jul 10, 2004 2:54 pm Post subject: |
|
|
kris wrote: | kris wrote: | ... a bunch of multicasting stuff that hasn't yet been tested on linux so, while I'm disappointed, I'm not too wildly surprised |
May have located the segfault by accident ~ will post again tomorrow, and place a beta_9a.zip on SVN |
Hey Kris,
After running across a post on the newsgroup, I realized that gdb could have some usefulness. Running mangotest within gdb produced the location of the segfault (I feel stupid for not trying this before):
0x0804eea7 in _D5mango2io6Buffer6Buffer5writeFDFAvZiZi ()
There appears to be a problem with a call to the write member in mang/io/Buffer.d.
Unfortunately, I'm having difficulty tracking down the location in unittest.d that makes this call... somewhere in testInvalidatee? I'll try adding some breakpoints. Command line gdb seems to be the only debugger that is actually useful for d on linux.
Was this the problem you fixed in the new beta?
(useing dmd 0.95)
Later,
John |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 3:14 pm Post subject: |
|
|
If you can, would you mind running testClassSerialization()? If that works then try testMulticast(), which requires a couple of CR hits to display anything.
Thanks much; |
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Sat Jul 10, 2004 3:28 pm Post subject: |
|
|
Yep no problem. Here are the results:
--- testClassSerialization() seemed to work. Output:
1090921693184 INFO mango.unittest - Done
(Now recompiling unittest/mango with testMulticast)
--- testMultcast() segfaulted. Output after 2 carriage returns:
listener received 1000 bytes
1090921695736 INFO mango.unittest - Done
Segmentation fault
--- Running the last test through gdb gave this result:
Program received signal SIGSEGV, Segmentation fault.
0x0806abad in _D3gcx3Gcx4markFPvPvZv()
I don't know what "mark" is... Are we getting any closer?
later,
John |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 3:46 pm Post subject: |
|
|
The logger output is amusing; look at those huge time stamps! Something to fix there
I'm guessing it's mango.io.SocketListener that's segfaulting. Can you insert a few juicy printf() into select locations within the run() method? For example:
Code: |
override int run()
{
printf (" listener enter\n");
while (true)
try {
// wait for incoming content
reader.read (buffer);
printf ("listener read() complete\n");
// time to quit?
if (quit || Socket.isCancelled())
break;
printf ("listener pre-notify\n");
// invoke callback
notify (buffer);
printf ("listener post-notify\n");
} catch (Object x)
{
printf ("listener exception\n");
// time to quit?
if (quit || Socket.isCancelled())
break;
printf ("SocketListener: ?.*s\n", x.toString());
//Stderr.put ("Exception: "~x.toString).cr();
}
printf ("listener exit\n");
return 0;
} |
|
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 3:56 pm Post subject: |
|
|
kris wrote: | The logger output is amusing; look at those huge time stamps! Something to fix there |
Fixed that one! |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 3:59 pm Post subject: |
|
|
JJR wrote: | 0x0806abad in _D3gcx3Gcx4markFPvPvZv() |
gdb is not so smart: heck ~ even the execution address say's there was "a bad" in the noted function ... |
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Sat Jul 10, 2004 4:03 pm Post subject: |
|
|
kris wrote: | JJR wrote: | 0x0806abad in _D3gcx3Gcx4markFPvPvZv() |
gdb is not so smart: heck ~ even the execution address say's there was "a bad" in the noted function ... |
LOL! |
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Sat Jul 10, 2004 4:10 pm Post subject: |
|
|
kris wrote: | The logger output is amusing; look at those huge time stamps! Something to fix there
I'm guessing it's mango.io.SocketListener that's segfaulting. Can you insert a few juicy printf() into select locations within the run() method. |
Ok... I've done so. It appears the catch{} exception path is not taken... The problem lies elsewhere, I guess. Here's the progression:
listener read() complete
listener pre-notify
listner received 1000 bytes
listener post-notify
1090921697497 INFO mango.unittest - Done
Segmentation fault
My question is: why did "listener exit" not get printed? |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 4:33 pm Post subject: |
|
|
hmmmm ... I was guessing at SocketListener since the exception happens after the main() thread says it's "done". A segfault happening after that is typically in a different thread which, in this case, is the SocketListener thread. You probably don't see "listener exit" because it segfaults before that point is reached, and before an exception is thrown within that thread.
The problem here is that the listener thread is blocked by the OS, waiting for some content to arrive on the socket. The only way to interrupt that is to ... interrupt it, which happens when the program exits. That's why there's those funky checks for 'quit' and so on within the catch{} block (we expect an exception here when the program exits and that socket-read is forceably terminated).
I'm wondering how to isolate this further. You might add a
Code: | byte x;
Stdin >> x; |
right before the return 0; of main(). At least that would further isolate the issue to the SocketListener() thread (a little pause can sometimes help).
You might also add a printf to the static destructor in mango.io.Socket, to see if and when that get's invoked. It's near the top of the file
Code: | static ~this()
{
printf ("static destructor\n");
Socket.cancelAll (true);
version(Win32)
{
WSACleanup();
}
} |
Another thing to try would be to add some printf() stuff within mango.io.DatagramSocket to see what the receive() method is returning:
Code: | int read (IBuffer target)
in {
assert (target);
}
body
{
int reader (void[] src)
{
int count = receive (src);
printf ("receive() ?d bytes\n", count);
if (count <= 0)
count = IConduit.Eof;
return count;
}
return target.write (&reader);
} |
|
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 5:06 pm Post subject: |
|
|
Another possibility is something barfing within a destructor ... I'll think about that one for a bit.
(BTW; all this stuff works perfectly under Win32 ~ including a variety of boundary conditions. We just have to unearth the linux gotcha's). |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 5:42 pm Post subject: |
|
|
Here a snapshot of the Win32 output for testMulticast()
listener received 1000 bytes
2015 INFO mango.unittest - Done
Socket static destructor
SocketListener: Failed while receiving socket data. Error # 10004
SocketListener: Failed while receiving socket data. Error # 10093
SocketListener: Failed while receiving socket data. Error # 10093
InBuffer destructor 'in'
InBuffer destructor 'out'
SocketListener destructor
I commented out the catch-block "we're quitting" test within SocketListener.run(), so you can see what's expected of that thread when the program exits (it throws a few exceptions).
I also added some destructor traces. Here's one (in unittest):
Code: |
void testMulticast()
{
class InBuffer : Buffer
{
char [] name;
this (int size, char[] name)
{
super (size);
this.name = name;
}
this (void[] x, int size, char[] name)
{
super (x, size);
this.name = name;
}
~this ()
{
printf ("InBuffer destructor '?.*s'\n", name);
}
}
MulticastSocket ms = new MulticastSocket ();
InternetAddress ia = new InternetAddress ("226.1.1.1", 4444);
byte[1000] xx;
Buffer b = new InBuffer (xx, xx.length, "out");
void listen (IBuffer buffer)
{
printf ("listener received ?d bytes\n", buffer.readable());
}
ms.join (ia);
ISocketListener s = new SocketListener (ms, new InBuffer(1500, "in"), &listen);
byte x;
Stdin >> x;
ms.write (b, ia);
Stdin >> x;
} |
and here's the other (in SocketListener):
Code: | ~this()
{
printf ("SocketListener destructor\n");
}
override int run()
{
while (true)
try {
// wait for incoming content
reader.read (buffer);
// time to quit?
if (quit || Socket.isCancelled())
break;
// invoke callback
notify (buffer);
} catch (Object x)
{
// time to quit?
//if (quit || Socket.isCancelled())
// break;
printf ("SocketListener: ?.*s\n", x.toString());
}
return 0;
}
|
|
|
Back to top |
|
|
JJR
Joined: 22 Feb 2004 Posts: 1104
|
Posted: Sat Jul 10, 2004 6:26 pm Post subject: |
|
|
With the changes, none of the destructors except ~Socket seem to get called. The program halts after printing out (as before):
listener received 1000 bytes
<big time #> INFO mango.unittest - Done
Socket.d: static destructor
Segmentation fault
Doesn't get further than this....
By the way, thanks for explaining about the thread ending after main... makes sense now. |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 6:44 pm Post subject: |
|
|
How about removing the Socket.d static destructor altogether? I wonder if there's a problem making a method call and/or assignment within a static destructor on linux?
Another thing to try would be to indicate, in testMulticast(), to the SocketListener that it should quit after just one good read (via method s.cancel):
Code: | ms.join (ia);
ISocketListener s = new SocketListener (ms, new Buffer(1500), &listen);
s.cancel();
byte x;
Stdin >> x;
ms.write (b, ia);
Stdin >> x; |
I'm hoping that will execute cleanly. Note that the notify() callback will not happen anymore, since it doesn't get called if 'quit' is flagged. If this works as expected, you might move the notify() call above the "quit" test in SocketListener.run() to see if it's the callback that screws things up ... |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 6:50 pm Post subject: |
|
|
JJR wrote: | <big time #> INFO mango.unittest - Done |
If you wanna' patch that huge timestamp before the next Beta, you could change mango.log.Event to have this inside the version(linux) section of the static constructor (should be around line 157):
Code: | beginTime = (cast(ulong) tv.tv_sec) * 1000 + tv.tv_usec / 1000; |
I had forgotten to put in the cast(ulong), so the expression was overflowing.
- Kris |
|
Back to top |
|
|
kris
Joined: 27 Mar 2004 Posts: 1494 Location: South Pacific
|
Posted: Sat Jul 10, 2004 7:11 pm Post subject: |
|
|
One of the nice things about CA is the number of reasonably good open-air concert theaters. Today the weather is far too nice to be coding and debugging, so I'm away to try and get very-last-minute tickets for Rush (gig starts in 1.5 hours) at my favourite open-air venue: Concord Pavillion.
Will check in later tonight. |
|
Back to top |
|
|
|