racket / htdp

Other
91 stars 69 forks source link

universe: internal custodian error when tcp-listen fails #125

Closed dvanhorn closed 3 years ago

dvanhorn commented 3 years ago

The universe server fails with an internal custodian error when tcp-listen fails, which can happen to students if they mistakenly run two universes from different DrRacket tabs (or with launch-many-worlds):

thread: the custodian has been shut down
  custodian: #<custodian>

The problem is that the exception handler here is calling stop!

https://github.com/racket/htdp/blob/b1e6aba39b31ad570785d777abc1a1591f39c6f4/htdp-lib/2htdp/private/universe.rkt#L177-L178

which shuts down the custodian:

https://github.com/racket/htdp/blob/b1e6aba39b31ad570785d777abc1a1591f39c6f4/htdp-lib/2htdp/private/universe.rkt#L214-L216

But then returns, and control reaches the call to (thread loop) here:

https://github.com/racket/htdp/blob/b1e6aba39b31ad570785d777abc1a1591f39c6f4/htdp-lib/2htdp/private/universe.rkt#L196

which results in the custodian error.

A simple fix would be to (raise x) after the call to (stop! x), which would give a better error message saying

tcp-listen: listen failed
  port number: 4567
  system error: Address already in use; errno=48

although you might want to report something even more beginner appropriate and point to the universe expression as the source.

(As a secondary note, the argument to stop! is never referenced.)

mfelleisen commented 3 years ago

@dvanhorn Highlighting the universe expression is wrong. It is syntactically correct even if when run later it tries to run a listener on the same port. Imagine

(define (multi-verse x] (universe ...))

and then (launch-many-worlds (multi-verse 1) (multi-verse 2)).

@dvanhorn Also, stop in the class doesn't use its argument but its overridden in both last-mixin and clock-mixin and one of them uses the argument.

mfelleisen commented 3 years ago

On second thought I did implement the highlighting of the universe expression.