Re: TCP Socket keepalive
Jan Wielemaker <[email protected]>
| Newsgroups | gmane.comp.ai.prolog.swi |
|---|---|
| Message-ID | <[email protected]> |
On 12/13/2013 06:44 AM, Haitao Zhang wrote: > Hi Jeff, > > Thanks for the explanation. What is interesting in my case is that the > tcp connection was definitely established. I intend it to be a long > session (it connects to a 127.0.0.x port to talk a local service), but > it sometimes loses the connection due to inactivity (more on this > later). At such times a write to the stream would raise an error, which > is expected. What is surprising is that close(Stream) also raises an > error. My guess is that the underlying stream has already been closed by > the native socket library unbeknownst to Prolog (I am on Windows), so > both actions raise the same WSAENOTSOCK error (I traced that far by > grepping the "Socket operation on non-socket" message). I am okay with > it although I would have expected close/1 to intercept the exception in > this case, since there is a well defined semantics here (close(close()) > == close() idempotent?). No. We are talking about streams. If you open a stream, write to it and close and get no error, you want the guarantee that all data has been transferred. So, close only succeeds if it successfully flushed the remaining buffer (if relevant) and can cleanly close the socket. There is close/2 with the option force(true) that closes the socket without worrying about errors. I.e., it performs the same operations, but succeeds no matter what happens. Otherwise, I think you are right and you need something that detects connection errors and reconnects for dealing with these scenarios ... > Now back to the original issue of keeping the connection, it seems that > TCP keepalive should really be used to detect failed connections and > release resources. TCP connection should not expire unless explicitly > released. What happened was: if my computer goes to sleep, after waking > up the Prolog client can send one packet successfully, but fails on the > second attempt. So it looks like some socket internal stuff fell out of > sync. But the server is unaware of this so it is not a reset from the > server side. Subsequently I can reconnect but open threads are piling up > on the server side. So I implemented tcp keepalive on the server side to > get rid of dead connections. Interestingly now the Prolog client side > starts to fail sooner -- I assume after the connection being idle for > two hours the server side starts sending keepalive packets to the client > side and the client side somehow shuts down the socket in response. Now > all of these could be completely internal to the winsock library so > Prolog would have no control over it, but I really can't tell. > > It seems that most people recommend application level keep-alive if one > wants to keep a connection around. > > > > On Wed, Dec 11, 2013 at 4:48 PM, Jeff Rosenwald <[email protected] > <mailto:[email protected]>> wrote: > > Hi Haitao: > > Supposing that your client looks something like this: > > client_stream(IPAddress, In, Out) :- > tcp_socket(S), > tcp_connect(S, IPAddress, In, Out). > > If client_stream/3 succeeds then In and Out will be unified with the > appropriate Prolog streams. If it succeeds, then safety requires > that you eventually close both streams using > "close(Stream, [force(true)])," and you must not release the socket > via tcp_close_socket/1 since it is no longer valid. > > BUT, it is perfectly reasonable to expect that occasionally the > above will throw an exception due the failure to connect. In that > case you *must not* close the streams since they are unbound and you > must release the socket using tcp_close_socket/1. If you don't then > the socket is leaked. > > Your client_stream/3 needs to look something like: > > client_stream(IPAddress, In, Out) :- > setup_call_catcher_cleanup(tcp_socket(Socket), > tcp_connect(Socket, IPAddress, > In, Out), > exception(_), > tcp_close_socket(Socket)). > > (Code not tested) > > Please see Section 6.2 of the clib docs to see how the socket should > be managed at this critical time. > > Regards, > Jeff R. > > -----Original Message----- > From: Haitao Zhang <[email protected] <mailto:[email protected]>> > To: Jan Wielemaker <[email protected] <mailto:[email protected]>> > Cc: swi-prolog <[email protected] > <mailto:[email protected]>> > Sent: Wed, Dec 11, 2013 3:08 am > Subject: Re: [SWIPL] TCP Socket keepalive > > Hi Jan, > > Thanks for the response. I will take a look at tcp_setopt/setsockopt. > > On a related note, after the send error (as the socket closed unexpectedly) > if I call close/1 on the stream, I get the same error. Now that is a little > confusing. Shouldn't close/1 just silently ignore the error? > tcp_close_socket on the other hand seems to gracefully handle the > situation. When I close down a channel, should I > > A) just call tcp_close_socket on the socket, and don't call close on the > stream? > > or > > B) do both, but wrap the close on the stream to trap the error condition? > It seems weird that one needs to wrap the close/1 since it should be in the > cleanup clause of an exception handler. > > Haitao > > > On Tue, Dec 10, 2013 at 12:57 AM, Jan Wielemaker <[email protected] <mailto:[email protected]>> wrote: > > > On 12/10/2013 08:26 AM, Haitao Zhang wrote: > > > >> I have a problem with the TCP socket, where SWI Prolog is client, > >> disappearing after some time (presumably some inactivity timer expired). I > >> have set my server side to keepalive, but that does not seem to help. > >> > >> The message I get from trying to use the socket again after a long idle > >> time: > >> ERROR: format/3: I/O error in write on stream <stream>(000000000834B260) > >> (Socket operation on non-socket) > >> > >> Any idea on how keep the socket alive? > >> > > > > There is tcp_setopt/2, which binds to setsockopt(). It doesn't support > > the SO_KEEPALIVE option yet. Should be easy enough to add. If you use > > a source version, see packages/clib. Try it and submit a patch with > > additional options you see fit. > > > > Hope this helps > > > > --- Jan > > > > > > > >> Thanks, > >> Haitao > >> -------------- next part -------------- > >> HTML attachment scrubbed and removed > >> _______________________________________________ > >> SWI-Prolog mailing list > >> [email protected] <mailto:[email protected]> > >> https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog > >> > >> > > > -------------- next part -------------- > HTML attachment scrubbed and removed > _______________________________________________ > SWI-Prolog mailing list > [email protected] <mailto:[email protected]> > https://lists.iai.uni-bonn.de/mailman/listinfo.cgi/swi-prolog > >