iilyak commented on PR #4729:
URL: https://github.com/apache/couchdb/pull/4729#issuecomment-1689015143

   > > I managed to find a way to seemingly detect the connection state change 
after the local client (curl) disconnects by querying the equivalent of 
`getsockopt(fd(), IPPROTO_TCP, TCP_CONNECTION_INFO, &info, &info_size)`
   > > ```
   > > ([email protected])22> rp(inet:getopts(#Port<0.24>, [{raw, 6, 262, 
1000}])).
   > > {ok,[{raw,6,262,
   > >           <<4,6,6,0,7,0,0,0,0,0,0,0,0,0,0,0,204,63,0,0,0,192,255,
   > >             63,18,0,2,0,0,57,6,0,0,0,0,0,88,58,6,0,1,0,0,0,1,0,0,
   > >             0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,177,1,0,0,0,0,0,0,
   > >             0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,148,0,0,0,0,0,0,0,0,
   > >             0,0,0,0,0,0,0,0,0,0,0,0,0,0,0>>}]}
   > > ok
   > > ```
   > 
   > This is nice. If we can cleanly encapsulate it in mochiweb then it might 
be a viable option. I am planing to look into mochiweb code to see if it is 
doable.
   
   I came to the same conclusion as Nick. It is quite a hack especially given 
the fact that it only would work on Linux. I also looked into using 
undocumented function unrecv. Which can be called in a quick succession after a 
recv.
   
   ```
   ([email protected])49> f(Port), Port = hd(lists:reverse(erlang:ports())).
   #Port<0.54>
   ([email protected])51> f(Res), Res = inet_tcp:recv(Port, 1, 10).
   {error,timeout}
   ([email protected])52> inet_tcp:unrecv(Port, <<>>).
   ok
   ([email protected])53> f(Res), Res = inet_tcp:recv(Port, 1, 10).
   {error,closed}
   ([email protected])54> inet_tcp:unrecv(Port, <<>>).
   ok
   ```  
   
   ```erlang
   still_connected(Socket) ->
       // read one byte with 10ms timeout
       case recv(Socket, 1, 10) of
           {error, timeout} ->
               true;
           {ok, Data} ->
               gen_tcp:unrecv(Socket, Data),
               true;
           {error, closed} ->
               false
       end.
   ```
   
   We could use `timer:apply_after/4` to call `still_connected/1`. However the 
problem is that timer:apply_after would be called concurrently. Therefore there 
is a chance that the request handler process would call recv in between 
recv/unrecv. This means we need locking. We could implement locking using `ets` 
table, BUT. 
   
   The conclusion is it is not easy.   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to