Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdbdc717

Browse files
Teach DSM registry to retry entry initialization if needed.
If DSM registry entry initialization fails, backends could try touse an uninitialized DSM segment, DSA, or dshash table (since theentry is still added to the registry). To fix, restructure thecode so that the registry retries initialization as needed. Thiscommit also modifies pg_get_dsm_registry_allocations() to leave outpartially-initialized entries, as they shouldn't have any allocatedmemory.DSM registry entry initialization shouldn't fail often in practice,but retrying was deemed better than leaving entries in apermanently failed state (as was done by commit1165a93, whichhas since been reverted).Suggested-by: Robert Haas <robertmhaas@gmail.com>Reviewed-by: Robert Haas <robertmhaas@gmail.com>Discussion:https://postgr.es/m/E1vJHUk-006I7r-37%40gemulon.postgresql.orgBackpatch-through: 17
1 parent1476028 commitdbdc717

File tree

1 file changed

+78
-43
lines changed

1 file changed

+78
-43
lines changed

‎src/backend/storage/ipc/dsm_registry.c‎

Lines changed: 78 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,10 @@ init_dsm_registry(void)
155155
{
156156
/* Initialize dynamic shared hash table for registry. */
157157
dsm_registry_dsa=dsa_create(LWTRANCHE_DSM_REGISTRY_DSA);
158+
dsm_registry_table=dshash_create(dsm_registry_dsa,&dsh_params,NULL);
159+
158160
dsa_pin(dsm_registry_dsa);
159161
dsa_pin_mapping(dsm_registry_dsa);
160-
dsm_registry_table=dshash_create(dsm_registry_dsa,&dsh_params,NULL);
161162

162163
/* Store handles in shared memory for other backends to use. */
163164
DSMRegistryCtx->dsah=dsa_get_handle(dsm_registry_dsa);
@@ -188,6 +189,8 @@ GetNamedDSMSegment(const char *name, size_t size,
188189
DSMRegistryEntry*entry;
189190
MemoryContextoldcontext;
190191
void*ret;
192+
NamedDSMState*state;
193+
dsm_segment*seg;
191194

192195
Assert(found);
193196

@@ -210,36 +213,36 @@ GetNamedDSMSegment(const char *name, size_t size,
210213
init_dsm_registry();
211214

212215
entry=dshash_find_or_insert(dsm_registry_table,name,found);
216+
state=&entry->dsm;
213217
if (!(*found))
214218
{
215-
NamedDSMState*state=&entry->dsm;
216-
dsm_segment*seg;
217-
218219
entry->type=DSMR_ENTRY_TYPE_DSM;
220+
state->handle=DSM_HANDLE_INVALID;
221+
state->size=size;
222+
}
223+
elseif (entry->type!=DSMR_ENTRY_TYPE_DSM)
224+
ereport(ERROR,
225+
(errmsg("requested DSM segment does not match type of existing entry")));
226+
elseif (state->size!=size)
227+
ereport(ERROR,
228+
(errmsg("requested DSM segment size does not match size of existing segment")));
229+
230+
if (state->handle==DSM_HANDLE_INVALID)
231+
{
232+
*found= false;
219233

220234
/* Initialize the segment. */
221235
seg=dsm_create(size,0);
222236

237+
if (init_callback)
238+
(*init_callback) (dsm_segment_address(seg));
239+
223240
dsm_pin_segment(seg);
224241
dsm_pin_mapping(seg);
225242
state->handle=dsm_segment_handle(seg);
226-
state->size=size;
227-
ret=dsm_segment_address(seg);
228-
229-
if (init_callback)
230-
(*init_callback) (ret);
231243
}
232-
elseif (entry->type!=DSMR_ENTRY_TYPE_DSM)
233-
ereport(ERROR,
234-
(errmsg("requested DSM segment does not match type of existing entry")));
235-
elseif (entry->dsm.size!=size)
236-
ereport(ERROR,
237-
(errmsg("requested DSM segment size does not match size of existing segment")));
238244
else
239245
{
240-
NamedDSMState*state=&entry->dsm;
241-
dsm_segment*seg;
242-
243246
/* If the existing segment is not already attached, attach it now. */
244247
seg=dsm_find_mapping(state->handle);
245248
if (seg==NULL)
@@ -250,10 +253,9 @@ GetNamedDSMSegment(const char *name, size_t size,
250253

251254
dsm_pin_mapping(seg);
252255
}
253-
254-
ret=dsm_segment_address(seg);
255256
}
256257

258+
ret=dsm_segment_address(seg);
257259
dshash_release_lock(dsm_registry_table,entry);
258260
MemoryContextSwitchTo(oldcontext);
259261

@@ -274,6 +276,7 @@ GetNamedDSA(const char *name, bool *found)
274276
DSMRegistryEntry*entry;
275277
MemoryContextoldcontext;
276278
dsa_area*ret;
279+
NamedDSAState*state;
277280

278281
Assert(found);
279282

@@ -292,14 +295,28 @@ GetNamedDSA(const char *name, bool *found)
292295
init_dsm_registry();
293296

294297
entry=dshash_find_or_insert(dsm_registry_table,name,found);
298+
state=&entry->dsa;
295299
if (!(*found))
296300
{
297-
NamedDSAState*state=&entry->dsa;
298-
299301
entry->type=DSMR_ENTRY_TYPE_DSA;
302+
state->handle=DSA_HANDLE_INVALID;
303+
state->tranche=-1;
304+
}
305+
elseif (entry->type!=DSMR_ENTRY_TYPE_DSA)
306+
ereport(ERROR,
307+
(errmsg("requested DSA does not match type of existing entry")));
308+
309+
if (state->tranche==-1)
310+
{
311+
*found= false;
300312

301313
/* Initialize the LWLock tranche for the DSA. */
302314
state->tranche=LWLockNewTrancheId(name);
315+
}
316+
317+
if (state->handle==DSA_HANDLE_INVALID)
318+
{
319+
*found= false;
303320

304321
/* Initialize the DSA. */
305322
ret=dsa_create(state->tranche);
@@ -309,17 +326,11 @@ GetNamedDSA(const char *name, bool *found)
309326
/* Store handle for other backends to use. */
310327
state->handle=dsa_get_handle(ret);
311328
}
312-
elseif (entry->type!=DSMR_ENTRY_TYPE_DSA)
329+
elseif (dsa_is_attached(state->handle))
313330
ereport(ERROR,
314-
(errmsg("requested DSAdoes not match type of existing entry")));
331+
(errmsg("requested DSAalready attached to current process")));
315332
else
316333
{
317-
NamedDSAState*state=&entry->dsa;
318-
319-
if (dsa_is_attached(state->handle))
320-
ereport(ERROR,
321-
(errmsg("requested DSA already attached to current process")));
322-
323334
/* Attach to existing DSA. */
324335
ret=dsa_attach(state->handle);
325336
dsa_pin_mapping(ret);
@@ -346,6 +357,7 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
346357
DSMRegistryEntry*entry;
347358
MemoryContextoldcontext;
348359
dshash_table*ret;
360+
NamedDSHState*dsh_state;
349361

350362
Assert(params);
351363
Assert(found);
@@ -365,45 +377,57 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
365377
init_dsm_registry();
366378

367379
entry=dshash_find_or_insert(dsm_registry_table,name,found);
380+
dsh_state=&entry->dsh;
368381
if (!(*found))
369382
{
370-
NamedDSHState*dsh_state=&entry->dsh;
371-
dshash_parametersparams_copy;
372-
dsa_area*dsa;
373-
374383
entry->type=DSMR_ENTRY_TYPE_DSH;
384+
dsh_state->dsa_handle=DSA_HANDLE_INVALID;
385+
dsh_state->dsh_handle=DSHASH_HANDLE_INVALID;
386+
dsh_state->tranche=-1;
387+
}
388+
elseif (entry->type!=DSMR_ENTRY_TYPE_DSH)
389+
ereport(ERROR,
390+
(errmsg("requested DSHash does not match type of existing entry")));
391+
392+
if (dsh_state->tranche==-1)
393+
{
394+
*found= false;
375395

376396
/* Initialize the LWLock tranche for the hash table. */
377397
dsh_state->tranche=LWLockNewTrancheId(name);
398+
}
399+
400+
if (dsh_state->dsa_handle==DSA_HANDLE_INVALID)
401+
{
402+
dshash_parametersparams_copy;
403+
dsa_area*dsa;
404+
405+
*found= false;
378406

379407
/* Initialize the DSA for the hash table. */
380408
dsa=dsa_create(dsh_state->tranche);
381-
dsa_pin(dsa);
382-
dsa_pin_mapping(dsa);
383409

384410
/* Initialize the dshash table. */
385411
memcpy(&params_copy,params,sizeof(dshash_parameters));
386412
params_copy.tranche_id=dsh_state->tranche;
387413
ret=dshash_create(dsa,&params_copy,NULL);
388414

415+
dsa_pin(dsa);
416+
dsa_pin_mapping(dsa);
417+
389418
/* Store handles for other backends to use. */
390419
dsh_state->dsa_handle=dsa_get_handle(dsa);
391420
dsh_state->dsh_handle=dshash_get_hash_table_handle(ret);
392421
}
393-
elseif (entry->type!=DSMR_ENTRY_TYPE_DSH)
422+
elseif (dsa_is_attached(dsh_state->dsa_handle))
394423
ereport(ERROR,
395-
(errmsg("requested DSHashdoes not match type of existing entry")));
424+
(errmsg("requested DSHashalready attached to current process")));
396425
else
397426
{
398-
NamedDSHState*dsh_state=&entry->dsh;
399427
dsa_area*dsa;
400428

401429
/* XXX: Should we verify params matches what table was created with? */
402430

403-
if (dsa_is_attached(dsh_state->dsa_handle))
404-
ereport(ERROR,
405-
(errmsg("requested DSHash already attached to current process")));
406-
407431
/* Attach to existing DSA for the hash table. */
408432
dsa=dsa_attach(dsh_state->dsa_handle);
409433
dsa_pin_mapping(dsa);
@@ -439,6 +463,17 @@ pg_get_dsm_registry_allocations(PG_FUNCTION_ARGS)
439463
Datumvals[3];
440464
boolnulls[3]= {0};
441465

466+
/* Do not show partially-initialized entries. */
467+
if (entry->type==DSMR_ENTRY_TYPE_DSM&&
468+
entry->dsm.handle==DSM_HANDLE_INVALID)
469+
continue;
470+
if (entry->type==DSMR_ENTRY_TYPE_DSA&&
471+
entry->dsa.handle==DSA_HANDLE_INVALID)
472+
continue;
473+
if (entry->type==DSMR_ENTRY_TYPE_DSH&&
474+
entry->dsh.dsa_handle==DSA_HANDLE_INVALID)
475+
continue;
476+
442477
vals[0]=CStringGetTextDatum(entry->name);
443478
vals[1]=CStringGetTextDatum(DSMREntryTypeNames[entry->type]);
444479

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp