IllegalReferenceCountException - Error during IO write phase on couchbase-2.0.3

@unhuman yeah with BinaryDocument you have more responsibilities. We expose the Netty ByteBuf, which can be an off-heap pooled buffer of bytes, so it needs to be managed explicitly to make sure it is returned to the pool and no memory leaks.

Notice that the SDK will release() the buffer whenever it writes it into a message (same as it does with other types of documents actually, this is deeper down the internals).

But since you potentially reuse this buffer in your particular write case, you should increment its reference counter for things to go smoothly:

byteBuffer.retain(); //prepare for potential multi usage (+1 refCnt, refCnt = 2)
try {
   bucket.append(document);
   // refCnt = 2 on success
   byteBuffer.release(); //refCnt = 1
} catch (DocumentDoesNotExistException dneException) {
   // buffer is released on errors, refCnt = 1
   //second usage will also release, but we want to be at refCnt = 1 for the finally block
   byteBuffer.retain(); //refCnt = 2
   bucket.insert(document); //refCnt = 1
} // other uncaught errors will still cause refCnt to be released down to 1
finally {
   //we made sure that at this point refCnt = 1 in any case (success, caught exception, uncaught exception)
   byteBuffer.release(); //refCnt = 0, returned to the pool
}
```

Alternatively:

byteBuffer.retain(); //prepare for potential multi usage (+1 refCnt, refCnt = 2)
try {
bucket.append(document);
// refCnt = 2 on success
byteBuffer.release(2); //success path, free buffer
} catch (DocumentDoesNotExistException dneException) {
// buffer is released (refCnt = 1) on errors, and second usage will free it
bucket.insert(document); //frees buffer
} catch (Exception others) {
// other uncaught errors will still cause refCnt to be released down to 1
// free the buffer by calling release() once more since it’s not used in this path
byteBuffer.release();
}


You have to prepare for the fact before the exception is caught because you cannot `retain()` a buffer that's been `release()` down to a `refCnt()` of 0.
1 Like