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

SIGSEGV error while accessing the BackupEngine methods #13335

Closed
tarun11Mavani opened this issue Jan 27, 2025 · 2 comments
Closed

SIGSEGV error while accessing the BackupEngine methods #13335

tarun11Mavani opened this issue Jan 27, 2025 · 2 comments

Comments

@tarun11Mavani
Copy link

I need some help with RocksDB BackupEngine setup.

Specs:

  • Version: rocksdbjni-9.7.4
  • OS: MacOS M3 Max 15.2 (24C101)
  • Java Version: 11

I am trying to use BackupEngine to take RocksDB backup. After initialising the BackupEngine, I am calling the createNewBackup method to take backup of the current state. However, this calls fails immediately and the process stops with SIGSEGV (0xb) at pc=0x000000011f0a2c48, pid=72021, tid=5123 error (logs attached in the end).

I tried running a simple java process to reproduce the issue and found the same error. Here is how I am initialising the RocksDB and BackupEngine instances. I am then calling backupEngine.createNewBackup(rocksDb) method. The getBackupInfo method call is also failing with same error.

Code for RocksDB initialization:

public class RocksDBTable {

  private static final Logger LOGGER = LoggerFactory.getLogger(App.class);
  public RocksDB _rocksDB;
  public BackupEngine _backupEngine;
  private final String _name = "myTable";
  public final String ROCKSDB_DIR = "/tmp/rocks";
  public final String ROCKSDB_BACKUP_DIR = ROCKSDB_DIR + "backup/" + _name;

  static {
    RocksDB.loadLibrary();
  }

  RocksDBTable() {
    _rocksDB = loadRocksDB();
    _backupEngine = loadBackupEngine();
  }

  public synchronized RocksDB loadRocksDB() {
    synchronized (App.class) {
      if (_rocksDB != null) {
        LOGGER.info("Using existing RocksDB for table name: {}", _name);
        return _rocksDB;
      } else {
        long writeBufferSize = 64 * 1024 * 1024;
        final Options options = new Options();
        options.setCreateIfMissing(true);
        options.setWriteBufferSize(writeBufferSize);
        options.setMaxBackgroundJobs(Runtime.getRuntime().availableProcessors() / 2);
        options.setIncreaseParallelism(Runtime.getRuntime().availableProcessors() / 2);
        File dbDir = new File(ROCKSDB_DIR, _name);
        clearRocksDBFiles(_name, dbDir);
        try {
          Files.createDirectories(dbDir.getParentFile().toPath());
          Files.createDirectories(dbDir.getAbsoluteFile().toPath());
          try (StdErrLogger stdErrLogger = new StdErrLogger(InfoLogLevel.DEBUG_LEVEL, _name)) {
            options.setLogger(stdErrLogger);
            RocksDB rocksDB = RocksDB.open(options, dbDir.getAbsolutePath());
            return rocksDB;
          }
        } catch (IOException | RocksDBException e) {
          LOGGER.error("Error initializing RocksDB", e);
          throw new RuntimeException(e);
        }
      }
    }
  }

  public void clearRocksDBFiles(String dbName, File dbDir) {
    // delete files inside dbDir
    if (dbDir.exists()) {
      LOGGER.info("deleting files: {} under dbDir: {} for table: {}", dbDir.listFiles(), dbDir.getAbsolutePath(),
          dbName);
      for (File file : Objects.requireNonNull(dbDir.listFiles())) {
        if (!file.delete()) {
          LOGGER.warn("Failed to delete file: {}", file.getAbsolutePath());
        }
      }
    }
    File lockFile = new File(dbDir, "LOCK");
    if (lockFile.exists()) {
      LOGGER.warn("Deleting stale lock file: " + lockFile.getAbsolutePath());
      lockFile.delete();
    }
  }

  public BackupEngine loadBackupEngine() {

    if (_backupEngine != null) {
      return _backupEngine;
    } else {
      File backupDir = new File(ROCKSDB_BACKUP_DIR);
      try {
        Files.createDirectories(backupDir.getParentFile().toPath());
        Files.createDirectories(backupDir.getAbsoluteFile().toPath());
      } catch (Exception e) {
        LOGGER.error("Error creating backup RocksDB directory.", e);
        throw new RuntimeException(e);
      }

      try (BackupEngineOptions backupEngineOptions = new BackupEngineOptions(backupDir.getAbsolutePath());
          BackupEngine backupEngine = BackupEngine.open(Env.getDefault(), backupEngineOptions)) {
        // BackupEngine is now ready for use
        return backupEngine;
      } catch (RocksDBException e) {
        // Handle exceptions
        throw new RuntimeException(e);
      }
    }
  }

  public void backup()
      throws RocksDBException {
    _backupEngine.createNewBackup(_rocksDB, false);
  }

  public void put(String key, String value)
      throws RocksDBException {
    //convert key value in string to byte[]
    byte[] keyBytes = key.getBytes();
    byte[] valueBytes = value.getBytes();

    _rocksDB.put(keyBytes, valueBytes);
  }

  public String get(String key)
      throws RocksDBException {
    return new String(_rocksDB.get(key.getBytes()));
  }

  public void clear() {
    _rocksDB.close();
  }

  public void restore()
      throws RocksDBException {
    _backupEngine.restoreDbFromLatestBackup(
        ROCKSDB_BACKUP_DIR, ROCKSDB_BACKUP_DIR,
        new RestoreOptions(false));
  }
}

Usage:

public class App 
{
    public static void main( String[] args )
        throws RocksDBException {
        RocksDBTable rocksDBTable = new RocksDBTable();
        rocksDBTable.put("key1", "value1");
        rocksDBTable.backup();
        //rocksDBTable.clear();
        //rocksDBTable.restore();;
        System.out.println(rocksDBTable.get("key1"));
    }
}

The process stops after the rocksDBTable.backup() call. Here is the error logs.


#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000000122806c48, pid=71314, tid=3843
#
# JRE version: Java(TM) SE Runtime Environment 18.9 (11.0.24+7) (build 11.0.24+7-LTS-271)
# Java VM: Java HotSpot(TM) 64-Bit Server VM 18.9 (11.0.24+7-LTS-271, mixed mode, tiered, compressed oops, g1 gc, bsd-aarch64)
# Problematic frame:
# C  [librocksdbjni7171456329043460129.jnilib+0x2c48]  Java_org_rocksdb_BackupEngine_createNewBackup+0x50
#
# No core dump will be written. 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:
#   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.
#

---------------  S U M M A R Y ------------

Command Line: -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=56596:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8 org.example.App

Host: Mac15,8 arm64 1 MHz, 16 cores, 64G, Darwin 24.2.0
Time: Mon Jan 27 16:46:19 2025 IST elapsed time: 0.434186 seconds (0d 0h 0m 0s)

---------------  T H R E A D  ---------------

Current thread (0x000000012680e000):  JavaThread "main" [_thread_in_native, id=3843, stack(0x000000016d78c000,0x000000016d98f000)]

Stack: [0x000000016d78c000,0x000000016d98f000],  sp=0x000000016d98e890,  free space=2058k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [librocksdbjni7171456329043460129.jnilib+0x2c48]  Java_org_rocksdb_BackupEngine_createNewBackup+0x50
j  org.rocksdb.BackupEngine.createNewBackup(JJZ)V+0
j  org.rocksdb.BackupEngine.createNewBackup(Lorg/rocksdb/RocksDB;Z)V+30
j  org.example.RocksDBTable.backup()V+50
j  org.example.App.main([Ljava/lang/String;)V+41
v  ~StubRoutines::call_stub
V  [libjvm.dylib+0x31a7b4]  JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, Thread*)+0x224
V  [libjvm.dylib+0x369a64]  jni_invoke_static(JNIEnv_*, JavaValue*, _jobject*, JNICallType, _jmethodID*, JNI_ArgumentPusher*, Thread*)+0x10c
V  [libjvm.dylib+0x36d60c]  jni_CallStaticVoidMethod+0x17c
C  [libjli.dylib+0x5a78]  JavaMain+0xb34
C  [libjli.dylib+0x7b40]  ThreadJavaMain+0xc
C  [libsystem_pthread.dylib+0x72e4]  _pthread_start+0x88

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.rocksdb.BackupEngine.createNewBackup(JJZ)V+0
j  org.rocksdb.BackupEngine.createNewBackup(Lorg/rocksdb/RocksDB;Z)V+30
j  org.example.RocksDBTable.backup()V+50
j  org.example.App.main([Ljava/lang/String;)V+41
v  ~StubRoutines::call_stub

siginfo: si_signo: 11 (SIGSEGV), si_code: 2 (SEGV_ACCERR), si_addr: 0x0000000000000028
@tarun11Mavani
Copy link
Author

tarun11Mavani commented Jan 28, 2025

update: while running the program on assertion mode, I found that the BackupEngine is not owning the handle.
I called backup() immediately after creating the BackupEngine which works fine. Calling it after putting some values fails due to owningHandle being released.
How do I make sure that owningHandle is not set to false by RocksDB inside my process?

@tarun11Mavani
Copy link
Author

update: I was using a try-with-resource block to initialise the BackupEngine. The BackupEngine was released immediately on the C++ side as soon as I exit the try-with-resource block. initialising it in a regular try-catch block fixed the issue.

try {
        BackupEngineOptions backupEngineOptions = new BackupEngineOptions(tableBackupDir.getAbsolutePath());
        return BackupEngine.open(Env.getDefault(), backupEngineOptions);
      } catch (RocksDBException e) {
        throw new RuntimeException(e);
     }

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