Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Fix the SharedFileSetUnregister API.
authorAmit Kapila <akapila@postgresql.org>
Tue, 1 Sep 2020 02:41:39 +0000 (08:11 +0530)
committerAmit Kapila <akapila@postgresql.org>
Tue, 1 Sep 2020 02:41:39 +0000 (08:11 +0530)
Commit 808e13b282 introduced a few APIs to extend the existing Buffile
interface. In SharedFileSetDeleteOnProcExit, it tries to delete the list
element while traversing the list with 'foreach' construct which makes the
behavior of list traversal unpredictable.

Author: Amit Kapila
Reviewed-by: Dilip Kumar
Tested-by: Dilip Kumar and Neha Sharma
Discussion: https://postgr.es/m/CAA4eK1JhLatVcQ2OvwA_3s0ih6Hx9+kZbq107cXVsSWWukH7vA@mail.gmail.com

src/backend/storage/file/sharedfileset.c

index 8b96e81fffff9251408d0445e0f130e4d71a7098..859c22e79b621b88715d6b080859abddd9328a5f 100644 (file)
@@ -266,12 +266,16 @@ SharedFileSetOnDetach(dsm_segment *segment, Datum datum)
 static void
 SharedFileSetDeleteOnProcExit(int status, Datum arg)
 {
-   ListCell   *l;
-
-   /* Loop over all the pending shared fileset entry */
-   foreach(l, filesetlist)
+   /*
+    * Remove all the pending shared fileset entries. We don't use foreach() here
+    * because SharedFileSetDeleteAll will remove the current element in
+    * filesetlist. Though we have used foreach_delete_current() to remove the
+    * element from filesetlist it could only fix up the state of one of the
+    * loops, see SharedFileSetUnregister.
+    */
+   while (list_length(filesetlist) > 0)
    {
-       SharedFileSet *fileset = (SharedFileSet *) lfirst(l);
+       SharedFileSet *fileset = (SharedFileSet *) linitial(filesetlist);
 
        SharedFileSetDeleteAll(fileset);
    }
@@ -301,7 +305,7 @@ SharedFileSetUnregister(SharedFileSet *input_fileset)
        /* Remove the entry from the list */
        if (input_fileset == fileset)
        {
-           filesetlist = list_delete_cell(filesetlist, l);
+           filesetlist = foreach_delete_current(filesetlist, l);
            return;
        }
    }