Stay alive unless closed from menu
[WhereAmI.git] / NOTES.ssl-trouble
1 https://groups.google.com/d/topic/google-api-java-client/iSL2bzoy9jw/discussion
2
3 When an API call is performed over Apache HTTP client after long period of inactivity, this exception happens:
4
5 W/System.err(  350): java.io.IOException: SSL shutdown failed: I/O error during system call, Broken pipe
6 W/System.err(  350):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativeclose(Native Method)
7 W/System.err(  350):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:958)
8 W/System.err(  350):    at org.apache.http.impl.SocketHttpClientConnection.close(SocketHttpClientConnection.java:205)
9 W/System.err(  350):    at org.apache.http.impl.conn.DefaultClientConnection.close(DefaultClientConnection.java:161)
10 W/System.err(  350):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.close(AbstractPooledConnAdapter.java:158)
11 W/System.err(  350):    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
12 W/System.err(  350):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:410)
13 W/System.err(  350):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
14 W/System.err(  350):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
15 W/System.err(  350):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
16 W/System.err(  350):    at com.google.api.client.http.apache.ApacheHttpRequest.execute(ApacheHttpRequest.java:58)
17 W/System.err(  350):    at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:639)
18 W/System.err(  350):    at com.google.api.client.http.json.JsonHttpClient.execute(JsonHttpClient.java:257)
19 W/System.err(  350):    at com.google.api.client.googleapis.services.GoogleClient.execute(GoogleClient.java:121)
20 W/System.err(  350):    at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:67)
21 W/System.err(  350):    at com.google.api.services.calendar.Calendar$Events$List.execute(Calendar.java:2643)
22
23 Presumably the Apache HttpClient connection manager notices that connection(s) are stale and tries to close them before re-opening to execute the current request.
24
25 SocketHttpClientConnection.close looks like this:
26
27    public void close() throws IOException {
28        if (!this.open) {
29            return;
30        }
31        this.open = false;
32        Socket sock = this.socket;
33        try {
34            doFlush();
35            try {
36                try {
37                    sock.shutdownOutput();
38                } catch (IOException ignore) {
39                }
40                try {
41                    sock.shutdownInput();
42                } catch (IOException ignore) {
43                }
44            } catch (UnsupportedOperationException ignore) {
45                // if one isn't supported, the other one isn't either
46            }
47        } finally {
48            sock.close();
49        }
50    }
51
52 It does catch and ignore IOException from shutdown() calls. Having done shutdown for both read and write, the assumption is that sock.close() will never throw a spurious exception.
53
54 But in our case the socket is not a TCP socket, but an SSL one. Presumably, socket close() is executed by
55
56 org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:958)
57
58 I cannot find the source code of this module anywhere (there is no such file in the Apache Harmony tree). Anyway, my hypothesis is that while regular TCP socket close() succeeds when the peer is already gone, the implementation of close() in this class tries to close the SSL session prior to closing the TCP socket, and that involves sending a message over the underlying TCP connection. Possibly the IOException that happens if the peer has already closed the TCP connection should have been ignored in this case. And prossibly it is not. Therefore it is propagated upstream, and nobody upstream expects that close would throw an exception in such a trivial case.
59