Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash with 0.7.0 when maxNumReaders exceeded #229

Open
ivenhov opened this issue Jan 17, 2024 · 0 comments
Open

Crash with 0.7.0 when maxNumReaders exceeded #229

ivenhov opened this issue Jan 17, 2024 · 0 comments

Comments

@ivenhov
Copy link

ivenhov commented Jan 17, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant