ndmitchell / ghcid

Very low feature GHCi based IDE
Other
1.13k stars 114 forks source link

Q: Is there a recommended approach to dealing with ports? #195

Open Wizek opened 6 years ago

Wizek commented 6 years ago

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?

Wizek commented 6 years ago

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?

ndmitchell commented 6 years ago

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.

Wizek commented 6 years ago

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?

ndmitchell commented 6 years ago

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.