Skip to content

Commit 4e972ec

Browse files
Merge pull request #15941 from lisanna-dettwyler/fix-sqlite-race
Fix sqlite race in LocalStore
2 parents cbbc07c + 9934b5f commit 4e972ec

1 file changed

Lines changed: 23 additions & 8 deletions

File tree

src/libstore/local-store.cc

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,22 @@ LocalStore::LocalStore(ref<const Config> config)
266266
: "database schema needs migrating, but this cannot be done in read-only mode");
267267
}
268268

269+
auto acquireWriteLock = [&]() {
270+
if (!lockFile(globalLock.get(), ltWrite, false)) {
271+
printInfo("waiting for exclusive access to the Nix store...");
272+
// We have acquired a shared lock; release it to prevent deadlocks.
273+
// This can happen if someone else is trying to promote their read
274+
// lock into a write lock.
275+
lockFile(globalLock.get(), ltNone, false);
276+
lockFile(globalLock.get(), ltWrite, true);
277+
}
278+
};
279+
280+
Finally releaseLock([&] {
281+
if (globalLock)
282+
lockFile(globalLock.get(), ltNone, false);
283+
});
284+
269285
if (curSchema > nixSchemaVersion)
270286
throw Error("current Nix store schema is version %1%, but I only support %2%", curSchema, nixSchemaVersion);
271287

@@ -288,12 +304,7 @@ LocalStore::LocalStore(ref<const Config> config)
288304
"which is no longer supported. To convert to the new format,\n"
289305
"please upgrade Nix to version 1.11 first.");
290306

291-
if (!lockFile(globalLock.get(), ltWrite, false)) {
292-
printInfo("waiting for exclusive access to the Nix store...");
293-
lockFile(
294-
globalLock.get(), ltNone, false); // We have acquired a shared lock; release it to prevent deadlocks
295-
lockFile(globalLock.get(), ltWrite, true);
296-
}
307+
acquireWriteLock();
297308

298309
/* Get the schema version again, because another process may
299310
have performed the upgrade already. */
@@ -329,10 +340,14 @@ LocalStore::LocalStore(ref<const Config> config)
329340
lockFile(globalLock.get(), ltRead, true);
330341
}
331342

332-
else
343+
else {
344+
if (!config->readOnly)
345+
acquireWriteLock();
333346
openDB(*state, false);
347+
}
334348

335-
upgradeDBSchema(*state);
349+
if (!config->readOnly)
350+
upgradeDBSchema(*state);
336351

337352
/* Prepare SQL statements. */
338353
state->stmts->RegisterValidPath.create(

0 commit comments

Comments
 (0)