Q: Is there a recommended approach to dealing with ports?
When I run apps for development in GHCid with reflex-dom + jsaddle-warp I often run into the issue of
<interactive>: Network.Socket.bind: resource busy (Address already in use)
I suspect this is because jsaddle-warp internally does a forkIO, making GHCid unable to terminate it's port usage with a Ctrl+C interrupt. Although it is a bit suspicious how forkIO threads and port usage can survive a :reload, not sure whether that is supposed to happen or not. Or perhaps they are using foreign-store internally.
At any rate I wonder, are issues like this experienced by others as well, or just me? Are there any recommended ways for dealing with open ports (or resource handles in general) with GHCid?
For some strange reasons so far beyond my full comprehension, the port seems to be retained even in conjunction with issue #194. Quite baffling.
Reloading...
/home/wizek/sandbox/proj-2/src/Main.hs
... (Omitting lots of empty lines here likely due to GHCid's screen clearing. Not sure about other terminals but tmux allowed me to scroll back past this point.)
Loading stack ghci proj:exe:proj-dev ...
WARNING: Ignoring out of range dependency (allow-newer enabled): directory-1.3.0.0. shelly requires: >=1.1.0.0 && <1.3.0.0
proj-0.23.10: initial-build-steps (exe)
The following GHC options are incompatible with GHCi and have not been passed to it: -threaded -O2
Configuring GHCi with the following packages: proj
Using main module: 1. Package `proj' component exe:proj-dev with main-is file: /home/wizek/sandbox/proj-2/app/Main.hs
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/wizek/.ghci
[ 1 of 28] Compiling Module1 ( /home/wizek/sandbox/proj-2/src/Module1.hs, interpreted ) [flags changed]
[ 2 of 28] Compiling Module2 ( /home/wizek/sandbox/proj-2/src/Module2.hs, interpreted ) [flags changed]
[ 3 of 28] Compiling Module3 ( /home/wizek/sandbox/proj-2/src/Module3.hs, interpreted ) [flags changed]
... (Omitting long and likely inconsequential progress reporting.)
Running test...
<a href="http://localhost:3198">run</a>
<interactive>: Network.Socket.bind: resource busy (Address already in use)
Ran via
$ ghcid -W -c 'stack ghci --flag proj:-SomeFlag proj:exe:proj-dev' -T 'Main.main' -o ghcid-output.txt
Any ideas what might be going on here? How can the port be retained if the old GHCi process is killed?
Any chance an open connection to the port on the read side keeps it alive?
My standard approach is to use port 0 to allocate a free port and spawn differently each time.
Any chance an open connection to the port on the read side keeps it alive?
Could be, not sure how I could check that.
I like your 0 port suggestion, wasn't aware of that working like that. Though I often have a browser connecting on this port to render a page, so it might be quite a hassle to have to re-type it every time. Is that what you do sometimes?
On Windows you can see the open ports with: https://support.kaspersky.com/common/windows/101
The programs I had with launched on port 0 also used https://hackage.haskell.org/package/open-browser to spawn the web page. I wasn't doing this through ghcid though, so the test cycle was quite different.