Socket error while trying to save attachment to cb lite

Hello,

Recently I have been seeing errors while trying to create attachments in cb-lite 1.4. Below is the HTTP request i am doing.

http://localhost:5984/myDatabase/docId/attachmentName.jpg?rev=revId
Body: Image Binary data
Content-Type: image/jpeg

A PUT with the above request, return a err_empty_response. When I checked the device logs I found the below

01-16 12:58:36.496  3866  3866 D SystemWebChromeClient: file:///android_asset/www/build/main.js: Line 1441 : [object Object]
01-16 12:58:36.497  3866  3866 I chromium: [INFO:CONSOLE(1441)] "[object Object]", source: file:///android_asset/www/build/main.js (1441)
01-16 12:58:36.500  3866  4117 V Database: PUT _id=b1c7d993-bde2-4daf-bdc5-6d07eb8645c1, _rev=1-345f334481ad46a139d319804c0155ef (allowConflict=false)
01-16 12:58:36.504  3866  4117 V Database: Acme.Utils.ThreadPool(0)-PooledThread: Acme.Serve.Serve$ServeConnection@af0fb28 Begin transaction (level 0)
01-16 12:58:36.509  3866  4117 V Database: Acme.Utils.ThreadPool(0)-PooledThread: Acme.Serve.Serve$ServeConnection@af0fb28 Committing transaction (level 0)
01-16 12:58:36.523  3866  4117 V CBLite  : ---> Added: {b1c7d993-bde2-4daf-bdc5-6d07eb8645c1 #2-79cd01f371ce7f071f3c185ab3d0d565 @4} as seq 4
01-16 12:58:36.523  3866  4117 V Listener: RouterCallbackBlock.onResponseReady() START
01-16 12:58:36.523  3866  4117 V Listener: RouterCallbackBlock.onResponseReady() END
01-16 12:58:36.523  3866  4117 V Listener: CountDownLatch.await() START
01-16 12:58:36.523  3866  4117 V Listener: CountDownLatch.await() END

> 01-16 12:58:36.524 3866 4117 W System.err: [Wed Jan 16 12:58:36 CST 2019] TJWS: IO error: java.net.SocketException: sendto failed: EBADF (Bad file descriptor) in processing a request /inspections_db/b1c7d993-bde2-4daf-bdc5-6d07eb8645c1/1547665085801.jpg from /127.0.0.1:5984 / java.net.Socket

Interesting to note is that the attachment gets saved perfectly fine, but the PUT request fails. Any idea why this exception would be occurring ?

Environment
Android 6.0
CB-LITE 1.4
App Type: Hybrid
Plugin: https://github.com/sumeet-singh04/Couchbase-Lite-PhoneGap-Plugin

this looks like it is throwing error from Android. Does not look like throwing from cb lite. Is it peer 2 peer? Just wondering whether you have closed the socket connection on the receiving part of replication.

It seems to be a cb lite problem, since the java exception is point to the database we have on there

/inspections_db/b1c7d993-bde2-4daf-bdc5-6d07eb8645c1/1547665085801.jpg from /127.0.0.1:5984 / java.net.Socket
CB-Lite REST API does run by default on port 5984, and its clearly visible in the log.

I am using a Cordova plugin inside my Hybrid Mobile App without replication, may be the cordova plugin is doing something behind the scene.

So it seems like the IO error is being ignored, I looked into the source code and i think the IO error generated while closing the Blob file is being ignored

public boolean storeBlob(byte[] data, BlobKey outKey) {
        BlobKey newKey = keyForBlob(data);
        outKey.setBytes(newKey.getBytes());
        String path = getRawPathForKey(outKey);
        File file = new File(path);
        if (file.canRead()) {
            return true;
        }

        if (encryptionKey != null) {
            try {
                data = encryptionKey.encryptData(data);
            } catch (SymmetricKeyException e) {
                Log.w(Log.TAG_DATABASE, "BlobStore: Failed to encode data for " + path, e);
                return false;
            }
        }

        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            fos.write(data);
        } catch (FileNotFoundException e) {
            Log.e(Log.TAG_DATABASE, "BlobStore: Error opening file for output", e);
            return false;
        } catch (IOException ioe) {
            Log.e(Log.TAG_DATABASE, "BlobStore: Error writing to file", ioe);
            return false;
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    // ignore
            }
        }
    }
    return true;
}

catch (IOException e) {
// ignore
}

So is it fine to ignore the IO exception ?

I don’t think that’s related. You’re getting an exception from Couchbase Lite’s REST API server, not from the blob code. A failure to save a blob wouldn’t cause an error writing to the HTTP stream.

Yes, you are right, I later noticed the exception is occurring in TJWS. Anyway, is there a recommended way to handle this or something I should be doing differently to handle this ?

Maybe it’s an issue in TJWS? But I’m no Android expert; maybe @blake.meike can help…

My apologies for not getting on this earlier! So sorry!

I don’t have enough information to debug this. Can you supply a stacktrace for the error?

CountDownLatches make me nervous. Is that latch stalling the UI thread?