jarohen / chord

A library designed to bridge the gap between the triad of CLJ/CLJS, web-sockets and core.async.
439 stars 40 forks source link

Close received after close #36

Closed magnars closed 8 years ago

magnars commented 9 years ago

Hi!

When my server closes the websocket channel, the client throws an error:

WebSocket connection to 'ws://localhost:9009/gateways/0200000100000205/progress.ws' failed: Close received after close

and the ws-channel returns {:message nil}.

I've boiled the server code down to:

(with-channel request ws-ch
    {:format :json-kw}
    (go
      (>! ws-ch "testing")
      (<! (timeout 1000))
      (close! ws-ch)))

On the client I then first get {:message "testing"} and after 1 second, I get the above error, then {:message nil}.

My client code looks like this pared down:

(defn connect [uri]
  (let [c (chan)]
    (go
      (let [{:keys [ws-channel error]} (<! (ws-ch (str "ws://" (.-host js/location) uri) {:format :json}))]
        (when-not error
          (loop []
            (let [v (<! ws-channel)]
              (prn v)
              (if-let [{:keys [message error]} v]
                (cond
                  error (do
                          (prn error)
                          (recur))
                  message (do
                            (>! c message)
                            (recur))
                  :else (close! c))
                (close! c)))))))
    c))

Any idea what's going on?

Thanks!

jarohen commented 9 years ago

Hi Magnar - it's been a while since I've looked at this code, I'm afraid - will take a look!

James

magnars commented 9 years ago

Thanks James. Let me know if I can help with more debugging information in some way!

jarohen commented 9 years ago

I've managed to repro this pretty quickly - thanks for the small test case :)

Unfortunately I've now spent a fair bit of time debugging to no avail - from what I can tell it's the server side that's causing it, yet Chord (and http-kit within it) are only sending one 'close' to the websocket.

Will keep digging

jarohen commented 9 years ago

Ah. https://code.google.com/p/chromium/issues/detail?id=372776 suggests it might be an issue with Chrome devtools, and I can't seem to repro in Firefox. Is it the same for you?

magnars commented 9 years ago

Thanks for digging into this, much appreciated. Seems like it is indeed Chrome dev tools, I cannot reproduce this in Firefox. Sorry for the wild goose chase!

jarohen commented 9 years ago

No worries! Tbh, it's made me re-visit Chord, which is a good thing - I haven't had chance to give it much love recently!

James

magnars commented 9 years ago

Glad to hear it was of some use. :-)

There is one interesting thing to comment on: I do get that {:message nil}, so to work around this bug in Chrome, I have to add a conditional checking for an event that should never happen in core.async.

jarohen commented 9 years ago

Ah, that does seem like a bug on Chord's side!

jarohen commented 9 years ago

Have pushed 0.7.0-SNAPSHOT with a fix for this issue - it now returns 'nil', so you can tell when the channel's closed.

Let me know if this fixes your issue?

Cheers!

magnars commented 9 years ago

Wow, this is pretty weird. I am thankfully no longer getting the {:message nil} oddballs, but I get nil several times.

screen shot 2015-07-04 at 22 45 38

I can't explain it, really - there should be no recurring, so I can't really explain how it reaches the print statement more than once. Maybe I've done something crazy. I wouldn't spend any more time on it unless other people come crashing in here with similar reports. :-)

magnars commented 9 years ago

To be clear, the "up-to-date" message is sent once from the server, and then it closes the channel.

magnars commented 9 years ago

I realized now that my code is trying to re-open the websocket for a while after it closes, so that explains the weirdness in my screenshot. Disregard. :blush: The 0.7.0-SNAPSHOT seems to have worked as intended.

jarohen commented 8 years ago

:) thanks!