Sync fails with "The target server failed to respond"



  • With version 0.5.10.2 (installed via F-Droid) under Android 4.1, I now get this error:

    I/davdroid.SyncManager(23379): Fetching 460 new remote resource(s)
    I/davdroid.RemoteCollection(23379): Multi-getting 35 remote resource(s)
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "REPORT /calendars/__uids__/2faeac7a-0279-583d-8282-ce4c6cd37a6e/calendar/ HTTP/1.1[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Content-Type: text/xml; charset=UTF-8[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Depth: 0[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Content-Length: 4465[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Host: servername:8008[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Connection: Keep-Alive[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "User-Agent: DAVdroid/0.5.10.2-alpha[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Accept-Encoding: gzip,deflate[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "Authorization: Basic b2xpdmVyOnBhc3M=[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "[\r][\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "<C:calendar-multiget xmlns:C="urn:ietf:params:xml:ns:caldav" xmlns="DAV:">[\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "   <prop>[\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "      <C:calendar-data/>[\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "      <getetag/>[\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "   </prop>[\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "   <href>/calendars/__uids__/2faeac7a-0279-583d-8282-ce4c6cd37a6e/calendar/03081c1c-060b-41e6-848e-8552eec6a86b.ics</href>[\n]"
    

    ...

    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "   <href>/calendars/__uids__/2faeac7a-0279-583d-8282-ce4c6cd37a6e/calendar/cc08285a-2b75-47c0-9c9d-8010d7e404b3.ics</href>[\n]"
    D/ch.boye.httpclientandroidlib.wire(23379): http-outgoing-7 >> "</C:calendar-multiget>"
    D/class ch.boye.httpclientandroidlib.impl.conn.DefaultManagedHttpClientConnection(23379): http-outgoing-7: Close connection
    D/class ch.boye.httpclientandroidlib.impl.conn.DefaultManagedHttpClientConnection(23379): http-outgoing-7: Shutdown connection
    D/class ch.boye.httpclientandroidlib.impl.conn.DefaultManagedHttpClientConnection(23379): http-outgoing-7: Close connection
    E/davdroid.DavSyncAdapter(23379): I/O error
    E/davdroid.DavSyncAdapter(23379): ch.boye.httpclientandroidlib.NoHttpResponseException: The target server failed to respond
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:143)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:260)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:161)
    E/davdroid.DavSyncAdapter(23379): 	at java.lang.reflect.Method.invokeNative(Native Method)
    E/davdroid.DavSyncAdapter(23379): 	at java.lang.reflect.Method.invoke(Method.java:511)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.conn.CPoolProxy.invoke(CPoolProxy.java:138)
    E/davdroid.DavSyncAdapter(23379): 	at $Proxy5.receiveResponseHeader(Native Method)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:271)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:123)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.execchain.MainClientExec.execute(MainClientExec.java:254)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.execchain.RetryExec.execute(RetryExec.java:85)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
    E/davdroid.DavSyncAdapter(23379): 	at ch.boye.httpclientandroidlib.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    E/davdroid.DavSyncAdapter(23379): 	at at.bitfire.davdroid.webdav.WebDavResource.multiGet(WebDavResource.java:298)
    E/davdroid.DavSyncAdapter(23379): 	at at.bitfire.davdroid.resource.RemoteCollection.multiGet(RemoteCollection.java:88)
    E/davdroid.DavSyncAdapter(23379): 	at at.bitfire.davdroid.syncadapter.SyncManager.pullNew(SyncManager.java:187)
    E/davdroid.DavSyncAdapter(23379): 	at at.bitfire.davdroid.syncadapter.SyncManager.synchronize(SyncManager.java:87)
    E/davdroid.DavSyncAdapter(23379): 	at at.bitfire.davdroid.syncadapter.DavSyncAdapter.onPerformSync(DavSyncAdapter.java:93)
    E/davdroid.DavSyncAdapter(23379): 	at android.content.AbstractThreadedSyncAdapter$SyncThread.run(AbstractThreadedSyncAdapter.java:254)
    D/SyncManager(  572): failed sync operation rb2 (bitfire.at.davdroid), com.android.calendar, USER, earliestRunTime 158299076, SyncResult: stats [ numIoExceptions: 1]
    

    This is for a big calendar (460 items apparently); with a smaller calendar (~10-20 items) it works fine. With older versions (0.5.6 maybe?) this error didn't occur.

    The calendar is served by Darwin CalendarServer 2.4 running on Debian. It can be used fine with Thunderbird+Lightning.

    Not sure yet whether the problem is on server or client side... Does the backtrace ring any bells?


  • developer

    Not sure yet whether the problem is on server or client side... Does the backtrace ring any bells?

    Looks like a server problem. DAVdroid as sent a REPORT multi-get request, but the server didn't send anything back (apparently not even headers).



  • So I think this is caused by the server closing the (HTTP keep-alive) connection, but the client doesn't notice this (or notices too late). IIUC this is what happens:

    • client opens HTTP connection (HTTP 1.1, so keep-alive is implicitly enabled)
    • client sends PROPFIND request
    • server sends huge HTTP 1.1 response (Content-Length: 224076)
    • client has to a) receive and b) parse response, and c) create the REPORT request for first 35 items
    • a+b+c takes maybe 20-40 seconds; but the server closes the HTTP connection 15 seconds after it has finished sending its response (server calls shutdown() and close() on the socket) - this is due to the default "idle timeout" in Calendarserver being set to 15 seconds
    • client doesn't notice that server has closed connection, tries to send REPORT request over socket that is already closed on server side
    • server replies with TCP Reset packets, and client finally closes connection on his side, and raises error because it didn't get a response

    I have now worked around this problem by increasing the HTTP Keep-Alive timeout on server to 120 seconds, by adding these lines to /etc/caldavd/caldavd.plist:

        <key>IdleConnectionTimeOut</key>
        <integer>120</integer>
    

    (this is probably a good idea anyway, performance-wise).

    So the problem is aggravated by a large calendar, low-end phone (600 MHz) and low Keep-Alive timeout on server side.

    It would be nice if there was a way to make the client notice that the Keep-Alive connection is closed before it sends the next request. No idea at the moment how to do that.


  • developer

    Sounds reasonable, thanks for the debugging work. I will have a look at the Keep-Alive settings.


  • developer

    I have tried this out by setting the Keep-Alive time on our server to 2 secs and adding a Thread.sleep(5000) between two operations so that the stale connection problem can be reproduced: In DAVroid/0.5.11, the NoHttpResponseException (which is a soft I/O error) occurs because the HttpClient stale connection check is disabled AND there's not appropriate retry strategy.

    With the new DavHttpRequestRetryHandler, the request is retried on a new connection when the old connection has got stale (closed). The stale connection check is not required because at the moment, all used HTTP verbs are idempotent.


Log in to reply
 

Looks like your connection to Bitfire App Forums was lost, please wait while we try to reconnect.