Skip to content

Check entry before getting its descriptor#469

Merged
cb1kenobi merged 2 commits intomainfrom
fix-entry-ref
Mar 18, 2026
Merged

Check entry before getting its descriptor#469
cb1kenobi merged 2 commits intomainfrom
fix-entry-ref

Conversation

@cb1kenobi
Copy link
Copy Markdown
Contributor

rocksdb-js was causing Harper to crash while running tests. There must have been some async cleanup where a DBRegisitryEntry was being closed by two or more triggers (e.g. db close w/ ref count = 1 or shutdown). The registry entries are plain old pointers, so we need to check them before we use them.

this->columns.clear();

{
std::lock_guard<std::mutex> lock(this->listenerCallbacksMutex);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a defensive measure. Claude recommended it. I don't think it does anything, but better safe than sorry.

DEBUG_LOG("%p DBRegistry::CloseDB Purging descriptor for \"%s\"\n", instance.get(), path.c_str());
entry->descriptor->close();
// since the registry itself always has a ref, we need to check for ref count 1
if (entry && entry->descriptor && entry->descriptor.use_count() <= 1) {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what caused the actual segfault.

entry->descriptor->close();

// re-acquire the mutex to check and potentially remove the descriptor
{
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're gonna do a block scope for a mutex, might as well put it around the mutex instead of the entire if-block.

@github-actions
Copy link
Copy Markdown
Contributor

📊 Benchmark Results

get-sync.bench.ts

getSync() > random keys - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 23.68K ops/sec 42.23 40.83 606.793 0.117 118,410
🥈 rocksdb 2 12.25K ops/sec 81.61 77.92 27,094.479 1.06 61,268

getSync() > sequential keys - small key size (100 records)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 27.57K ops/sec 36.27 35.17 484.448 0.104 137,842
🥈 rocksdb 2 13.15K ops/sec 76.03 71.83 3,384.9 0.138 65,768

ranges.bench.ts

getRange() > small range (100 records, 50 range)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 lmdb 1 26.41K ops/sec 37.87 36.00 924.469 0.162 132,036
🥈 rocksdb 2 3.52K ops/sec 283.947 245.993 1,559.434 0.549 17,609

realistic-load.bench.ts

Realistic write load with workers > write variable records with transaction log

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 195.61 ops/sec 5,112.084 63.71 133,832.393 41.19 416
🥈 lmdb 2 26.37 ops/sec 37,921.441 270.481 1,193,208.838 136.628 64.00

transaction-log.bench.ts

Transaction log > read 100 iterators while write log with 100 byte records

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 37.26K ops/sec 26.84 13.64 14,293.82 0.595 186,324
🥈 lmdb 2 435.93 ops/sec 2,293.932 130.391 10,490.012 1.29 2,180

Transaction log > read one entry from random position from log with 1000 100 byte records

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 774.59K ops/sec 1.29 1.10 3,376.561 0.163 3,872,965
🥈 lmdb 2 449.66K ops/sec 2.22 1.16 1,021.639 0.298 2,248,291

worker-put-sync.bench.ts

putSync() > random keys - small key size (100 records, 10 workers)

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 850.90 ops/sec 1,175.224 990.106 1,791.769 0.329 1,702
🥈 lmdb 2 1.01 ops/sec 985,590.36 860,716.598 1,022,383.831 3.64 10.00

worker-transaction-log.bench.ts

Transaction log with workers > write log with 100 byte records

Implementation Rank Operations/sec Mean (ms) Min (ms) Max (ms) RME (%) Samples
🥇 rocksdb 1 18.45K ops/sec 54.21 30.26 492.403 0.492 36,892
🥈 lmdb 2 832.90 ops/sec 1,200.617 220.204 17,539.338 5.41 1,666

Results from commit e7b3ecc

Copy link
Copy Markdown
Member

@kriszyp kriszyp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you for tracking this down!

@cb1kenobi cb1kenobi merged commit 7919569 into main Mar 18, 2026
20 checks passed
@cb1kenobi cb1kenobi deleted the fix-entry-ref branch March 18, 2026 14:30
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

Successfully merging this pull request may close these issues.

2 participants