[racket] How to wait for tcp-accpt-evt unless the listener is or has been closed?
My first thought was
* We should add `tcp-listener-closed?'.
* The documentation should clarify that a listener becomes ready
(e.g., `sync' on a listener would return) when the listener is
closed as well as when it is ready to accept.
* You could combine a `sync' and a `tcp-listener-closed?' to wait
until either a connection is ready to accept or the listener is
closed.
But, of course, there would be a race condition between finding out
that the listener is ready to accept closing the connection on another
thread. Avoiding that race condition requires something more like an
option on `tcp-accept-evt' that determines its behavior (instead of
raising an exception) for a closed listener.
A simpler possibility is to use a custodian that manages both the
listener and the thread. Then, `custodian-shutdown-all' cleanly stops
them both. I recommend that approach, unless you need to make sure that
`receive-file' isn't interrupted.
At Thu, 13 Sep 2012 19:17:55 +0100, Erich Rast wrote:
> Hi all,
>
> I have a question about tcp-listener. I've implemented a simple
> filetransfer protocol whose main listener loop is this:
>
> (define (start-listen local-port save-path from-ip progress-proc final-proc
> [timeout 60.0] [file-table (make-hash)])
> (define listener (tcp-listen local-port 1 #t #f))
> (thread
> (lambda ()
> (progress-proc 'listening save-path 0)
> (let loop ((in-out-ports (sync/enable-break (tcp-accept-evt listener))))
> (receive-file (first in-out-ports) (second in-out-ports)
> save-path progress-proc final-proc file-table timeout)
> (loop (sync/enable-break (tcp-accept-evt listener))))))
> listener)
>
> In my tests, after transfering a file I call (just for fun) stop-listen:
>
> (define (stop-listen listener)
> (tcp-close listener))
>
> and the result is an exception. The problem is, how do I end the loop in the
> above thread when the listener is closed? Obviously,
>
> (when (port-closed? (first in-out-ports))
> (loop (sync/enable-break (tcp-accept-evt listener))))
>
> does not have the desired effect, because sync/enable-break is already
> waiting, so when the port is closed tcp-accept-evt correctly raises a network
> exception. Basically, I need a synchronizable event that yields #f if the
> listener is closed, the opened ports otherwise. But how? There is not even a
> tcp-listener-closed? method.
>
> Any suggestions?
>
> Best,
>
> Erich
> ____________________
> Racket Users list:
> http://lists.racket-lang.org/users