views:

107

answers:

3

In my mochiweb application, I am using a long held HTTP request. I wanted to detect when the connection with the user died, and I figured out how to do that by doing:

Socket = Req:get(socket),
inet:setopts(Socket, [{active, once}]),
receive
     {tcp_closed, Socket} ->
             % handle clean up
     Data ->
             % do something 
end.

This works when: user closes his tab/browser or refreshes the page. However, when the internet connection dies suddenly (say wifi signal lost all of a sudden), or when the browser crashes abnormally, I am not able to detect a tcp close.

Am I missing something, or is there any other way to achieve this?

+1  A: 

There isn't a default "keep alive" (but can be enabled if supported) protocol over TCP: in case there is a connection fault when no data is exchanged, this translates to a "silent failure". You would need to account for this type of failure by yourself e.g. implement some form of connection probing.

How does this affect HTTP? HTTP is a stateless protocol - this means that every request is independent of every other. The "keep alive" functionality of HTTP doesn’t change that i.e. "silent failure" can still occur.

Only when data is exchanged can this condition be detected (or when TCP Keep Alive is enabled).

jldupont
+1  A: 

There is a TCP keepalive protocol and it can be enabled with inet:setopts/2 under the option {keepalive, Boolean}.

I would suggest that you don't use it. The keep-alive timeout and max-retries tends to be system wide, and it is optional after all. Using timeouts on the protocol level is better.

The HTTP protocol has the status code Request Timeout which you can send to the client if it seems dead.

Check out the after clause in receive blocks that you can use to timeout waiting for data, or use the timer module, or use erlang:start_timer/3. They all have different performance characteristics and resource costs.

Christian
I considered using the after clause, but in this case, my process might be an hibernating process. Would the after clause still work for an hibernating process?
jeffreyveon
No, it would not. A hibernating process wakes up when a message is sent to it. There is no hibernation timeout, so have a delayed message delivered to you to wake up.
Christian