GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — SIGSEGV on `cursorIterable.next()` when the env is closed · Issue #185 · lmdbjava/lmdbjava

SIGSEGV on cursorIterable.next() when the env is closed #185

New issue
Copy link
New issue
Copy link
Closed
Closed
SIGSEGV on cursorIterable.next() when the env is closed#185
Copy link
Labels
pr-received

Description

@at055612
at055612
opened on Nov 4, 2021
Issue body actions

We have a use case where LMDB envs are created as transient stores for search result data so are created, filled, queried then closed and deleted when no longer needed. There are multiple threads involved. We had a bug in our app that resulted in the env being closed while a thread was still trying to query the lmdb db. This resulted in a SIGSEGV and our whole app going down.

I appreciate that querying the db after the env is closed is wrong, but it would be preferable to get an exception rather than have the whole app crash.

I added the following test to EnvTest to demonstrate this. I should imagine the same will happen with other cursor ops and possibly gets.

  @Test
  public void cannotReadOnceClosed() throws IOException, InterruptedException, ExecutionException {
    final File path = tmp.newFile();
    final Env<ByteBuffer> env = create()
            .setMaxReaders(5)
            .open(path, MDB_NOSUBDIR);

    final Dbi<ByteBuffer> dbi = env.openDbi(DB_1, MDB_CREATE);

    dbi.put(bb(1), bb(10));
    dbi.put(bb(2), bb(20));

    try (Txn<ByteBuffer> roTxn = env.txnRead()) {
      assertThat(dbi.get(roTxn, bb(1)).getInt(), is(10));
      assertThat(dbi.get(roTxn, bb(2)).getInt(), is(20));
    }

    System.out.println("Done puts");

    final CountDownLatch firstGetFinishedLatch = new CountDownLatch(1);
    final CountDownLatch envClosedLatch = new CountDownLatch(1);

    final CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {

      System.out.println("Running async task");
      try (Txn<ByteBuffer> roTxn = env.txnRead()) {
        try (CursorIterable<ByteBuffer> iterable = dbi.iterate(roTxn, KeyRange.all())) {
          final Iterator<CursorIterable.KeyVal<ByteBuffer>> iterator = iterable.iterator();

          try {
            System.out.println("Getting first entry");
            CursorIterable.KeyVal<ByteBuffer> keyVal = iterator.next();
            assertThat(keyVal.val().getInt(), is(10));

            firstGetFinishedLatch.countDown();

            try {
              System.out.println("Waiting for env to close");
              envClosedLatch.await();
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
              throw new RuntimeException(e);
            }

            assertThat(env.isClosed(), is(true));

            System.out.println("Getting second entry, but env is now closed");
            keyVal = iterator.next();
            assertThat(keyVal.val().getInt(), is(20));
          } catch (RuntimeException e) {
            e.printStackTrace();
          }
        }
      }
    });

    System.out.println("Waiting for cursor to get first entry");
    firstGetFinishedLatch.await();

    System.out.println("Closing env");
    env.close();
    envClosedLatch.countDown();

    System.out.println("Waiting for completion");
    future.get();
  }

This produces the output

Done puts
Waiting for cursor to get first entry
Running async task
Getting first entry
Waiting for env to close
Closing env
Waiting for completion
Getting second entry, but env is now closed
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fb5d37dab28, pid=2052, tid=2086
#
# JRE version: OpenJDK Runtime Environment (15.0.2+7) (build 15.0.2+7-27)
# Java VM: OpenJDK 64-Bit Server VM (15.0.2+7-27, mixed mode, sharing, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C  [lmdbjava-native-library-17311548015087855682.so+0x6b28]  mdb_cursor_next+0x138
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/dev/git_work/lmdbjava/hs_err_pid2052.log
#
# If you would like to submit a bug report, please visit:
#   https://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.
#

Process finished with exit code 134 (interrupted by signal 6: SIGABRT)

I have raised PR #186 with some added guards for the env being closed.

Activity

  1. at055612
    added 4 commits that reference this issue on Nov 4, 2021

    lmdbjavagh-185 Add protection for closed env

    3da5b06

    lmdbjavagh-185 Add env.checkNotClosed to Dbi.put

    303c9c0

    lmdbjavagh-185 Remove redundant test

    1bc841e

    lmdbjavagh-185 Remove unused imports

    46e41ff
  2. buko commented on Nov 30, 2021

    @buko
    buko
    on Nov 30, 2021
    More actions

    +1

    We've experienced this also and it is disconcerting... to say the least. In fact many times we don't even get the SIGSEGV error message -- the JVM simply terminates. No exception, no warning, no error message of any kind. It leads to a lot of confusion and panic. Ideally, lmdbjava really should just raise an exception instead of taking down the entire JVM but even if this is too difficult perhaps some sort of warning message could be reliably printed?

  3. bp-alex
    added
    pr-received
    on Apr 15, 2022
  4. bp-alex commented on Feb 3, 2023

    @bp-alex
    bp-alex
    on Feb 3, 2023
    Member
    More actions

    Safety checks for a closed Env included in PR #186 have now been merged.

    Reacted by at055612
  5. bp-alex
    closed this as completedon Feb 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    pr-received

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402520 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.