Hey Marc (and other relevant readers),
I found a bug with the remote debugger. At the end of a session with
a client (the running program), when the client exits and disconnects
from the remote debugger, the server halts with a "deadlock
detection." This seems to always happen with any program, so I wonder
if others are experiencing this.
I think I figured out what's going on, and I'm offering a fix. If
anyone has any opinions, let me know.
The relevant changes affect how the server reads incoming connections.
Before, it would create a server using OPEN-TCP-SERVER, wait for an
initial connection, and establish the connection and then use
THREAD-JOIN! from the primordial thread (thread A) to the writer
thread (thread B) to wait for everything to finish. It seems like the
design was to only have the server handle one client and then quit.
The problem with this is that thread B wasn't terminated properly, and
it sits there waiting for messages using THREAD-RECEIVE, while thread
A is waiting for it to finish. Essentially, when the network
connections quit and those threads die, you are left with thread A and
B in a deadlocked situation.
(That probably only makes sense to those who have studied Marc's
remote debugger, which might only be Marc.)
There are 2 solutions:
1. On the server, kill the writer thread at the appropriate time.
This is probably when it receives the message that the reader thread
has died, meaning that the client connection was lost. The server
would simply exit.
2. Change the server so that it loops and continually accepts new
client connections. It would only exit with a ^C.
I think #2 is better server design. It seems like it should stay
open, continually accepting new connections. This makes it very
usable as simply a background process.
Here are my changes to implement #2. You simple need to replace
RDI-OPEN-SERVER with this one:
(define (rdi-open-server rdi)
(let ((listen-port
(open-tcp-server
(list port-number: (rdi-port-num rdi)
reuse-address: #t))))
(let loop ()
(let ((connection
(read listen-port)))
(let ((request (read connection)))
(if (not (equal? request rdi-version1))
(error "unexpected debuggee version")
(begin
(write rdi-version2 connection)
(force-output connection)
(let ((reader-thread (rdi-create-reader-thread rdi connection)))
(rdi-connection-set! rdi connection)
(thread-start! reader-thread)
(loop)))))))))
Now, the main thread doesn't to use THREAD-JOIN!, but it simply loops
forever. So, the call (rdi-force-connection rdi) in debugger.scm
never returns, but starts the loop.
I've attached my current version of the remote debugger. It also
features a different server interface; you pass in the host/port when
running (gsi -:dar,h10000 debugger.scm 20000).
- James