Description
I know this is for an old version 0.7.0 and many things have changed but bear with me.
I'm planning to upgrade to the latest version but that requires code changes so for now I'm stuck and I would like to clarify this.
I have a test that crashes JVM with SIGSEGV on Ubuntu 16, arch is amd64
openjdk version "1.8.0_292"
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~16.04.1-b10)
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
Test configures lmdb with a following
- maxReaders=2
- other flags: MDB_NORDAHEAD, MDB_NOMEMINIT, MDB_NOTLS, MDB_NOSYNC, MDB_NOMETASYNC
The test executes various searches using 20 threads.
Soon after starting the test it crashes with below stacktrace killing JVM
The test was written purely to get the idea how library would behave under that circumstances.
First of all I was under the impression that LMDB would check limits and fail with an error as described here
#65
Second, I have a protection in place using Java's Semaphore to acquire and release when transactions are in use to avoid the problem.
It seems this is now working as expected, since the crash happens anyway, this is something I need to investigate.
Relevant code looks as follows
TxRead txnRead() {
try {
boolean acquired;
if (_readerAwaitTime == 0L)
acquired = _readSemaphore.tryAcquire();
else
acquired = _readSemaphore.tryAcquire(_readerAwaitTime, TimeUnit.MILLISECONDS);
if (!acquired)
throw new TimeoutRuntimeException("Timeout when waiting for read transaction");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
}
// semaphore acquired
try {
return new TxRead(_env.txnRead(), _readSemaphore);
} catch (Exception e) {
_readSemaphore.release();
throw e;
}
}
And client code
try (TxRead tx = txnRead(); IteratorAbstract it = buildIteratorForTerm(_term, tx.txn)) {
...
}
TxRead looks as follows
static class TxRead implements AutoCloseable {
Txn<ByteBuffer> txn;
private Semaphore semaphore;
TxRead(Txn<ByteBuffer> txn, Semaphore semaphore) {
this.txn = txn;
this.semaphore = semaphore;
}
@Override
public void close() {
synchronized (this) {
try {
if (txn != null)
txn.close();
} finally {
// nullify txn to avoid double close
txn = null;
// nullify semaphore to avoid double release
if (semaphore != null) {
semaphore.release();
semaphore = null;
}
}
}
}
}
Fatal error
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f905c639d44, pid=32565, tid=0x00007f903c10e700
#
# JRE version: OpenJDK Runtime Environment (8.0_292-b10) (build 1.8.0_292-8u292-b10-0ubuntu1~16.04.1-b10)
# Java VM: OpenJDK 64-Bit Server VM (25.292-b10 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# C [libpthread.so.0+0x9d44] pthread_mutex_lock+0x4
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Stacktrace
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
J 1445 org.lmdbjava.Library$Lmdb$jnr$ffi$0.mdb_txn_begin$jni$29(JJIJ)I (0 bytes) @ 0x00007f904544138a [0x00007f9045441340+0x4a]
J 1751 C2 org.lmdbjava.Env.txn(Lorg/lmdbjava/Txn;[Lorg/lmdbjava/TxnFlags;)Lorg/lmdbjava/Txn; (30 bytes) @ 0x00007f904555ad38 [0x00007f904555a940+0x3f8]
J 2615 C2 com.om.mxs.mdb.impl.CommandFindObjects.execute()V (254 bytes) @ 0x00007f9045721064 [0x00007f9045720ec0+0x1a4]
J 2037 C2 com.om.mxs.mdb.impl.MetadataDbWithLmdb.findAsCollection(Lcom/om/mxs/mdb/VaultId;Lcom/om/mxs/mdb/SearchTerm;Lcom/om/mxs/mdb/ObjectId;I)Ljava/util/Collection; (123 bytes) @ 0x00007f904565ac10 [0x00007f904565a960+0x2b0]
J 2049 C2 com.om.mxs.mdb.MetadataDbTestUtils.findWithAttribute(Lcom/om/mxs/mdb/VaultId;Lcom/om/mxs/mdb/ObjectAttribute;Lcom/om/mxs/mdb/ObjectId;I)[Lcom/om/mxs/mdb/ObjectId; (53 bytes) @ 0x00007f904565f2b8 [0x00007f904565f1e0+0xd8]
J 2610% C1 com.om.mxs.mdb.ReadersStressTest$Searcher.doRun()V (29 bytes) @ 0x00007f9045373d44 [0x00007f9045373aa0+0x2a4]
j com.om.mxs.mdb.ReadersStressTest$Searcher.run()V+1
v ~StubRoutines::call_stub
Any pointers why the crash happens instead of an error would be greatly appreciated
Thanks
Daniel