8000 Fix possible core dump in parallel restore when using a TOC list. · dirbacke/postgres@59dde9f · GitHub
[go: up one dir, main page]

Skip to content

Commit 59dde9f

Browse files
committed
Fix possible core dump in parallel restore when using a TOC list.
Commit 3eb9a5e unintentionally introduced an ordering dependency into restore_toc_entries_prefork(). The existing coding of reduce_dependencies() contains a check to skip moving a TOC entry to the ready_list if it wasn't initially in the pending_list. This used to suffice to prevent reduce_dependencies() from trying to move anything into the ready_list during restore_toc_entries_prefork(), because the pending_list stayed empty throughout that phase; but it no longer does. The problem doesn't manifest unless the TOC has been reordered by SortTocFromFile, which is how I missed it in testing. To fix, just add a test for ready_list == NULL, converting the call with NULL from a poor man's sanity check into an explicit command not to touch TOC items' list membership. Clarify some of the comments around this; in particular, note the primary purpose of the check for pending_list membership, which is to ensure that we can't try to restore the same item twice, in case a TOC list forces it to be restored before its dependency count goes to zero. Per report from Fabrízio de Royes Mello. Back-patch to 9.3, like the previous commit. Discussion: https://postgr.es/m/CAFcNs+pjuv0JL_x4+=71TPUPjdLHOXA4YfT32myj_OrrZb4ohA@mail.gmail.com
1 parent 4f86235 commit 59dde9f

File tree

1 file changed

+14
-9
lines changed

1 file changed

+14
-9
lines changed

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3634,8 +3634,9 @@ restore_toc_entries_prefork(ArchiveHandle *AH, TocEntry *pending_list)
36343634
*
36353635
* Note: as of 9.2, it should be guaranteed that all PRE_DATA items appear
36363636
* before DATA items, and all DATA items before POST_DATA items. That is
3637-
* not certain to be true in older archives, though, so this loop is coded
3638-
* to not assume it.
3637+
* not certain to be true in older archives, though, and in any case use
3638+
* of a list file would destroy that ordering (cf. SortTocFromFile). So
3639+
* this loop cannot assume that it holds.
36393640
*/
36403641
AH->restorePass = RESTORE_PASS_MAIN;
36413642
skipped_some = false;
@@ -3682,7 +3683,7 @@ restore_toc_entries_prefork(ArchiveHandle *AH, TocEntry *pending_list)
36823683

36833684
(void) restore_toc_entry(AH, next_work_item, ropt, false);
36843685

3685-
/* there should be no touch of ready_list here, so pass NULL */
3686+
/* Reduce dependencies, but don't move anything to ready_list */
36863687
reduce_dependencies(AH, next_work_item, NULL);
36873688
}
36883689
else
@@ -4360,7 +4361,7 @@ identify_locking_dependencies(ArchiveHandle *AH, TocEntry *te)
43604361
/*
43614362
* Remove the specified TOC entry from the depCounts of items that depend on
43624363
* it, thereby possibly making them ready-to-run. Any pending item that
4363-
* becomes ready should be moved to the ready list.
4364+
* becomes ready should be moved to the ready_list, if that's provided.
43644365
*/
43654366
static void
43664367
reduce_dependencies(ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
@@ -4377,15 +4378,19 @@ reduce_dependencies(ArchiveHandle *AH, TocEntry *te, TocEntry *ready_list)
43774378
otherte->depCount--;
43784379

43794380
/*
4380-
* It's ready if it has no remaining dependencies and it belongs in
4381-
* the current restore pass. However, don't move it if it has not yet
4382-
* been put into the pending list.
4381+
* It's ready if it has no remaining dependencies, and it belongs in
4382+
* the current restore pass, and it is currently a member of the
4383+
* pending list (that check is needed to prevent double restore in
4384+
* some cases where a list-file forces out-of-order restoring).
4385+
* However, if ready_list == NULL then caller doesn't want any list
4386+
* memberships changed.
43834387
*/
43844388
if (otherte->depCount == 0 &&
43854389
_tocEntryRestorePass(otherte) == AH->restorePass &&
4386-
otherte->par_prev != NULL)
4390+
otherte->par_prev != NULL &&
4391+
ready_list != NULL)
43874392
{
4388-
/* It must be in the pending list, so remove it ... */
4393+
/* Remove it from pending list ... */
43894394
par_list_remove(otherte);
43904395
/* ... and add to ready_list */
43914396
par_list_append(ready_list, otherte);

0 commit comments

Comments
 (0)
0