Skip to content

Commit 16cc274

Browse files
committed
Remove unnecessary spock_shmem_attach routine
Being loaded on startup, Spock always initializes its shared memory segment and shared HTABs in the postmaster process as well as all local pointers to shared memory. There is no case when the postmaster does not call shmem_startup_hook() after cleaning up its shared memory. Also, there is no case when the postmaster does any sensitive operations before initializing shared memory. In case of recovery, evidence that shared memory is already initialized and operable is the fact that redo operations can acquire locks. Remove the 'attach' routine and its calls in checkpoint hook and bgworker initialization to make the code more straightforward, reduce the code base, and reduce potential errors. Additional code quality improvements: - Clarify TODO comment about undefined behavior with padding bytes - Improve function documentation for return values (spock_group_progress_update) - Remove redundant Assert statement that duplicated runtime check - Clarify comments about progress structure initialization This is a partial revert of commit c436818.
1 parent 7cf409e commit 16cc274

File tree

6 files changed

+50
-172
lines changed

6 files changed

+50
-172
lines changed

include/spock_group.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ typedef struct SpockGroupEntry
156156

157157
/* shmem setup */
158158
extern void spock_group_shmem_request(void);
159-
extern void spock_group_shmem_startup(int napply_groups, bool found);
159+
extern void spock_group_shmem_startup(int napply_groups);
160160

161161
SpockGroupEntry *spock_group_attach(Oid dbid, Oid node_id, Oid remote_node_id);
162162
void spock_group_detach(void);

include/spock_worker.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ extern void handle_sigterm(SIGNAL_ARGS);
159159
extern void spock_subscription_changed(Oid subid, bool kill);
160160

161161
extern void spock_worker_shmem_init(void);
162-
extern void spock_shmem_attach(void);
163162

164163
extern int spock_worker_register(SpockWorker *worker);
165164
extern void spock_worker_attach(int slot, SpockWorkerType type);

src/spock_group.c

Lines changed: 7 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -113,16 +113,13 @@ spock_group_shmem_request(void)
113113
* Initialize shared resources for db-origin management
114114
*/
115115
void
116-
spock_group_shmem_startup(int napply_groups, bool found)
116+
spock_group_shmem_startup(int napply_groups)
117117
{
118118
HASHCTL hctl;
119119

120120
if (prev_shmem_startup_hook != NULL)
121121
prev_shmem_startup_hook();
122122

123-
if (SpockGroupHash)
124-
return;
125-
126123
MemSet(&hctl, 0, sizeof(hctl));
127124
hctl.keysize = sizeof(SpockGroupKey);
128125
hctl.entrysize = sizeof(SpockGroupEntry);
@@ -137,35 +134,16 @@ spock_group_shmem_startup(int napply_groups, bool found)
137134
HASH_SHARED_MEM | HASH_PARTITION |
138135
HASH_FIXED_SIZE);
139136

140-
if (!SpockGroupHash)
141-
elog(ERROR, "spock_group_shmem_startup: failed to init group map");
142-
143-
/*
144-
* If the shared memory structures already existed (found = true), then
145-
* we're a background process attaching to structures created by the
146-
* postmaster. The hash was already seeded from the file during postmaster
147-
* startup, so skip loading.
148-
*
149-
* If found = false, we're the postmaster doing initial setup. Load the
150-
* file to quickly seed the hash, then WAL recovery will run afterward and
151-
* provide authoritative updates.
152-
*
153-
* Note: ShmemInitHash() doesn't have a 'found' output parameter like
154-
* ShmemInitStruct(), so we rely on the 'found' status of other Spock
155-
* structures (SpockCtx, etc.) as a proxy since they're all created
156-
* together.
157-
*/
158-
if (found)
159-
return;
160-
161-
elog(DEBUG1, "spock_group_shmem_startup: loading resource file to seed hash");
162137
spock_group_resource_load();
138+
elog(DEBUG1,
139+
"spock_group_shmem_startup: loading resource file to seed hash. loaded records: %lu",
140+
hash_get_num_entries(SpockGroupHash));
163141
}
164142

165143
/*
166-
* TODO:
167-
* here is always looming issue with UB around padding until we implement
168-
* our own 'hash' and 'cmp' routines for the key operations.
144+
* TODO: There is a looming issue with undefined behavior (UB) due to
145+
* uninitialized padding bytes in the key structure. We should implement
146+
* custom hash and comparison routines that avoid memcmp on padded structs.
169147
*/
170148
static inline SpockGroupKey
171149
make_key(Oid dbid, Oid node_id, Oid remote_node_id)
@@ -617,15 +595,6 @@ spock_checkpoint_hook(XLogRecPtr checkPointRedo, int flags)
617595
if ((flags & (CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_END_OF_RECOVERY)) == 0)
618596
return;
619597

620-
/*
621-
* Ensure we're attached to shared memory before accessing it.
622-
*
623-
* spock_shmem_attach() is idempotent - it tracks attachment per process
624-
* and only does the actual work once, so it's safe to call on every
625-
* qualifying checkpoint.
626-
*/
627-
spock_shmem_attach();
628-
629598
/* Dump group progress to resource.dat */
630599
spock_group_resource_dump();
631600
}

src/spock_output_plugin.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,8 +1403,6 @@ spock_output_plugin_shmem_startup(void)
14031403

14041404
/* Get the shared resources */
14051405
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
1406-
SpockCtx->slot_group_master_lock = &((GetNamedLWLockTranche("spock_slot_groups")[0]).lock);
1407-
SpockCtx->slot_ngroups = nworkers;
14081406
slot_groups = ShmemInitStruct("spock_slot_groups",
14091407
spock_output_plugin_shmem_size(nworkers),
14101408
&found);

src/spock_rmgr.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -156,15 +156,6 @@ spock_rmgr_identify(uint8 info)
156156
void
157157
spock_rmgr_startup(void)
158158
{
159-
/*
160-
* During WAL recovery in the startup process, we need to attach to the
161-
* shared memory structure (SpockGroupHash) that was created by the
162-
* postmaster's shmem_startup_hook.
163-
*
164-
* spock_shmem_attach() handles resetting inherited globals and properly
165-
* re-attaching to shared memory before WAL replay begins.
166-
*/
167-
spock_shmem_attach();
168159
}
169160

170161
void

src/spock_worker.c

Lines changed: 42 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static void wait_for_worker_startup(SpockWorker *worker,
7979
BackgroundWorkerHandle *handle);
8080
static void signal_worker_xact_callback(XactEvent event, void *arg);
8181
static uint32 spock_ch_stats_hash(const void *key, Size keysize);
82-
static bool spock_shmem_init_internal(int nworkers);
82+
static void spock_shmem_init_internal(int nworkers);
8383

8484

8585
void
@@ -344,15 +344,6 @@ spock_worker_on_exit(int code, Datum arg)
344344
void
345345
spock_worker_attach(int slot, SpockWorkerType type)
346346
{
347-
/*
348-
* Ensure shared memory is attached before using SpockCtx.
349-
*
350-
* Background workers inherit global variables from the postmaster but the
351-
* pointers may not be valid. Always call spock_shmem_attach() which is
352-
* idempotent and handles proper re-initialization.
353-
*/
354-
spock_shmem_attach();
355-
356347
Assert(slot >= 0);
357348
Assert(slot < SpockCtx->total_workers);
358349

@@ -838,9 +829,18 @@ spock_worker_shmem_startup(void)
838829
* This is kludge for Windows (Postgres does not define the GUC variable
839830
* as PGDLLIMPORT)
840831
*/
841-
nworkers = atoi(GetConfigOptionByName("max_worker_processes", NULL,
842-
false));
832+
nworkers = atoi(GetConfigOptionByName("max_worker_processes", NULL, false));
833+
834+
/*
835+
* Reset in case this is a restart within the postmaster
836+
* Spock extension must be loaded on startup. In case of a fatal error and
837+
* further restart, postmaster clean up shared memory but local variables
838+
* stay the same. So, we need to clean outdated pointers in advance.
839+
*/
843840
SpockCtx = NULL;
841+
SpockHash = NULL;
842+
SpockGroupHash = NULL;
843+
exception_log_ptr = NULL;
844844

845845
/* Avoid possible race-conditions when initializing shared memory. */
846846
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);
@@ -850,7 +850,7 @@ spock_worker_shmem_startup(void)
850850
* This internally calls spock_group_shmem_startup() to handle group
851851
* initialization and file loading.
852852
*/
853-
(void) spock_shmem_init_internal(nworkers);
853+
spock_shmem_init_internal(nworkers);
854854

855855
LWLockRelease(AddinShmemInitLock);
856856
}
@@ -878,70 +878,52 @@ spock_ch_stats_hash(const void *key, Size keysize)
878878
* This centralizes the logic for setting up all Spock shared memory pointers,
879879
* which is used by both the initial startup hook and the attach function.
880880
*/
881-
static bool
881+
static void
882882
spock_shmem_init_internal(int nworkers)
883883
{
884884
HASHCTL hctl;
885885
bool found;
886-
bool all_found = true;
887-
888886

889887
/* Init signaling context for the various processes. */
890-
if (!SpockCtx)
888+
SpockCtx = ShmemInitStruct("spock_context",
889+
worker_shmem_size(nworkers, false), &found);
890+
if (!found)
891891
{
892-
SpockCtx = ShmemInitStruct("spock_context",
893-
worker_shmem_size(nworkers, false), &found);
894-
if (!SpockCtx)
895-
elog(ERROR, "failed to initialize spock_context");
896-
897-
if (!found)
898-
{
899-
/* First time - initialize the structure */
900-
SpockCtx->lock = &((GetNamedLWLockTranche("spock")[0]).lock);
901-
SpockCtx->apply_group_master_lock = &((GetNamedLWLockTranche(SPOCK_GROUP_TRANCHE_NAME)[0]).lock);
902-
SpockCtx->supervisor = NULL;
903-
SpockCtx->subscriptions_changed = false;
904-
SpockCtx->total_workers = nworkers;
905-
memset(SpockCtx->workers, 0,
906-
sizeof(SpockWorker) * SpockCtx->total_workers);
907-
all_found = false;
908-
}
892+
/* First time - initialize the structure */
893+
SpockCtx->lock = &((GetNamedLWLockTranche("spock")[0]).lock);
894+
SpockCtx->apply_group_master_lock = &((GetNamedLWLockTranche(SPOCK_GROUP_TRANCHE_NAME)[0]).lock);
895+
SpockCtx->slot_group_master_lock = &((GetNamedLWLockTranche("spock_slot_groups")[0]).lock);
896+
SpockCtx->slot_ngroups = nworkers;
897+
SpockCtx->supervisor = NULL;
898+
SpockCtx->subscriptions_changed = false;
899+
SpockCtx->total_workers = nworkers;
900+
memset(SpockCtx->workers, 0,
901+
sizeof(SpockWorker) * SpockCtx->total_workers);
909902
}
910903

911904
/*
912905
* Initialize exception log pointer array.
913906
*/
914-
if (!exception_log_ptr)
915-
{
916-
exception_log_ptr = ShmemInitStruct("spock_exception_log_ptr",
917-
worker_shmem_size(nworkers, false), &found);
918-
if (!exception_log_ptr)
919-
elog(ERROR, "failed to initialize spock_exception_log_ptr");
907+
exception_log_ptr = ShmemInitStruct("spock_exception_log_ptr",
908+
worker_shmem_size(nworkers, false), &found);
920909

921-
if (!found)
922-
{
923-
memset(exception_log_ptr, 0, sizeof(SpockExceptionLog) * nworkers);
924-
all_found = false;
925-
}
910+
if (!found)
911+
{
912+
memset(exception_log_ptr, 0, sizeof(SpockExceptionLog) * nworkers);
926913
}
927914

928915
/*
929916
* Initialize SpockHash - channel stats hash.
930917
*/
931-
if (!SpockHash)
932-
{
933-
memset(&hctl, 0, sizeof(hctl));
934-
hctl.keysize = sizeof(spockStatsKey);
935-
hctl.entrysize = sizeof(spockStatsEntry);
936-
hctl.hash = spock_ch_stats_hash;
937-
SpockHash = ShmemInitHash("spock channel stats hash",
938-
spock_stats_max_entries,
939-
spock_stats_max_entries,
940-
&hctl,
941-
HASH_ELEM | HASH_FUNCTION | HASH_FIXED_SIZE);
942-
if (!SpockHash)
943-
elog(ERROR, "failed to initialize spock channel stats hash");
944-
}
918+
memset(&hctl, 0, sizeof(hctl));
919+
hctl.keysize = sizeof(spockStatsKey);
920+
hctl.entrysize = sizeof(spockStatsEntry);
921+
hctl.hash = spock_ch_stats_hash;
922+
SpockHash = ShmemInitHash("spock channel stats hash",
923+
spock_stats_max_entries,
924+
spock_stats_max_entries,
925+
&hctl,
926+
HASH_ELEM | HASH_FUNCTION | HASH_FIXED_SIZE);
945927

946928
/*
947929
* Initialize SpockGroupHash via the spock_group module. This handles both
@@ -950,68 +932,7 @@ spock_shmem_init_internal(int nworkers)
950932
* Note: We pass 'all_found' to indicate whether this is first-time setup
951933
* or attachment to existing structures.
952934
*/
953-
spock_group_shmem_startup(nworkers, all_found);
954-
955-
return all_found;
956-
}
957-
958-
/*
959-
* spock_shmem_attach
960-
*
961-
* Attach (or re-attach) to existing shared memory structures.
962-
*
963-
* This is called from processes that need to access Spock's shared memory:
964-
* - Startup process (via spock_rmgr_startup) - once per recovery
965-
* - Checkpointer (via spock_checkpoint_hook) - once per process lifetime
966-
* - Background workers (via spock_worker_attach) - once per worker
967-
*
968-
* IMPORTANT: Auxiliary processes (startup, checkpointer) inherit global
969-
* variable values from the postmaster, but these pointers might not be valid
970-
* in their address space.
971-
*
972-
* This function uses a static flag to ensure we only attach once per process,
973-
* avoiding redundant shared memory lookups on subsequent calls.
974-
*
975-
* Unlike spock_worker_shmem_startup(), this doesn't acquire AddinShmemInitLock
976-
* or register hooks - it just looks up and attaches to existing structures.
977-
*/
978-
void
979-
spock_shmem_attach(void)
980-
{
981-
static bool attached = false;
982-
int nworkers;
983-
984-
/* If already attached in this process, nothing to do */
985-
if (attached)
986-
return;
987-
988-
/*
989-
* Reset globals to NULL to force proper attachment.
990-
*
991-
* This is critical for auxiliary processes (startup, checkpointer) that
992-
* inherit invalid global values from the postmaster.
993-
*/
994-
SpockCtx = NULL;
995-
SpockHash = NULL;
996-
SpockGroupHash = NULL;
997-
exception_log_ptr = NULL;
998-
999-
/*
1000-
* Get max_worker_processes to know the size of structures.
1001-
*/
1002-
nworkers = atoi(GetConfigOptionByName("max_worker_processes", NULL, false));
1003-
if (nworkers <= 0)
1004-
nworkers = 9;
1005-
1006-
/*
1007-
* Attach to all structures using the common initialization logic. Returns
1008-
* true if structures were found (normal case), false if they had to be
1009-
* created (shouldn't happen but harmless).
1010-
*/
1011-
(void) spock_shmem_init_internal(nworkers);
1012-
1013-
/* Mark as attached to avoid redundant work on subsequent calls */
1014-
attached = true;
935+
spock_group_shmem_startup(nworkers);
1015936
}
1016937

1017938
/*

0 commit comments

Comments
 (0)