Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to sendTextData after receiveData gets an async exception. #182

Open
michalrus opened this issue Sep 28, 2018 · 6 comments
Open

Unable to sendTextData after receiveData gets an async exception. #182

michalrus opened this issue Sep 28, 2018 · 6 comments
Labels

Comments

@michalrus
Copy link

It’s not possible to implement something like:

do
  msg <- timeout (10*1000*1000) (receiveData conn)
  case msg of
    Just msg -> 
    Nothing ->
      sendTextData conn "timeouted"
      threadDelay (1 * 1000 * 1000) -- even with this…
      sendClose conn

… the client will never see the "timeouted" message.

@jaspervdj
Copy link
Owner

@michalrus Yes, receiveData blocks until data is received (just like most of the lower-level networking functions in Haskell). In order to send and receive, you can use forkIO (or something like the async) package to kick off a writer thread. Does that solve your problem?

@michalrus
Copy link
Author

Well, that receive blocks is understandable.

What I want is a time-outing receive.

So if you wrap it in http://hackage.haskell.org/package/base-4.12.0.0/docs/System-Timeout.html, the wrapped call returns with a Nothing, but then sendTextData called later on does… nothing.

System.Timeout.timeout works by sending an async exception to the current thread.

@jaspervdj
Copy link
Owner

Oh! I completely misunderstood the question, sorry. Yes, that makes sense to have.

@jaspervdj
Copy link
Owner

I think we should implement this the nice way but that will be a breaking change. We basically want to be able to extend Stream's interface with a Success | FatalError | Timeout result type from read and pass in an optional timeout.

As for the API, do you think the timeout should be global (i.e. set on socket/stream creation) or local (i.e. a parameter to receive)?

@michalrus
Copy link
Author

I see…

IMO, local — see also #32. =)

I mean, these issues (+ the ones with ping timeout #174 #159) can certainly be worked around either like proposed by @rwbarton in #32, or some other way with Async, but they would be nice to have natively — being explicit about the fact that networking is, in essence, unreliable. ¯\_(ツ)_/¯

Also not all programmers might be able to implement this correctly, so it’s a better task for the library.

Cf. fallacy 1. of https://en.wikipedia.org/wiki/Fallacies_of_distributed_computing:

The network is reliable.

Software applications are written with little error-handling on networking errors. During a network outage, such applications may stall or infinitely wait for an answer packet, permanently consuming memory or other resources. When the failed network becomes available, those applications may also fail to retry any stalled operations or require a (manual) restart.

@michalrus
Copy link
Author

Also, similar to this, imagine:

finally
  (forever $ receiveTextData conn >>= processMsgSomehow)
  (sendTextData conn "bye bye")

If I throw an async exception to this simple code above, sendTextData will throw a Network.WebSockets.ConnectionClosed exception despite WAI thread clearly still being alive (the finally hook happens in that WAI thread).

These API choices of WebSockets prevent writing slightly more, hmmm, refined(?) code, like the one above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants