Skip to content

Commit

Permalink
Prevent race condition when starting bgw
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-- committed Jan 16, 2025
1 parent d28ea29 commit a16675b
Showing 1 changed file with 39 additions and 0 deletions.
39 changes: 39 additions & 0 deletions src/pgduckdb_background_worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ extern "C" {
#include "miscadmin.h"
#include "pgstat.h"
#include "executor/spi.h"
#include "common/file_utils.h"
#include "postmaster/bgworker.h"
#include "postmaster/interrupt.h"
#include "storage/ipc.h"
Expand Down Expand Up @@ -57,10 +58,17 @@ static bool is_background_worker = false;
static std::unordered_map<std::string, std::string> last_known_motherduck_catalog_versions;
static uint64 initial_cache_version = 0;

bool CanTakeLockForDatabase(Oid database_oid);

extern "C" {

PGDLLEXPORT void
pgduckdb_background_worker_main(Datum /* main_arg */) {
elog(LOG, "started pg_duckdb background worker");
if (!CanTakeLockForDatabase(0)) {
elog(LOG, "pg_duckdb background worker: could not take lock for database '%u'. Will exit.", 0);
return;
}
// Set up a signal handler for SIGTERM
pqsignal(SIGTERM, die);
BackgroundWorkerUnblockSignals();
Expand Down Expand Up @@ -151,6 +159,36 @@ bool HasBgwRunningForMyDatabase() {
return false;
}

/*
Attempts to take a lock on a file named 'pgduckdb_worker_<database_oid>.lock'
If the lock is taken, the function returns true. If the lock is not taken, the function returns false.
*/
bool CanTakeLockForDatabase(Oid database_oid) {
char lock_file_name[MAXPGPATH];
snprintf(lock_file_name, MAXPGPATH, "%s/%s.pgduckdb_worker.%d",
DataDir, PG_TEMP_FILE_PREFIX,
database_oid);

auto fd = open(lock_file_name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
if (fd < 0) {
auto err = strerror(errno);
elog(ERROR, "Could not take lock on file '%s': %s", lock_file_name, err);
}

// Take exclusive lock on the file
auto ret = flock(fd, LOCK_EX | LOCK_NB);
if (ret == EWOULDBLOCK) {
return false;
}

if (ret != 0) {
auto err = strerror(errno);
elog(ERROR, "Could not take lock on file '%s': %s", lock_file_name, err);
}

return true;
}

/*
Will start the background worker if:
- MotherDuck is enabled (TODO: should be database-specific)
Expand Down Expand Up @@ -640,6 +678,7 @@ SyncMotherDuckCatalogsWithPg_Cpp(bool drop_with_cascade) {
if (current_motherduck_catalog_version) {
pfree(current_motherduck_catalog_version);
}

current_motherduck_catalog_version = pstrdup(catalog_version.c_str());
MemoryContextSwitchTo(old_context);

Expand Down

0 comments on commit a16675b

Please sign in to comment.