At Wed, 28 Oct 2020 19:03:14 +0900, Masahiko Sawada <masahiko.saw...@2ndquadrant.com> wrote in > On Wed, 29 Jul 2020 at 10:37, Justin Pryzby <pry...@telsasoft.com> wrote: > > > > On Mon, Jul 27, 2020 at 05:39:02AM -0500, Justin Pryzby wrote: > > > On Mon, Jul 27, 2020 at 08:00:46PM +1200, Thomas Munro wrote: > > > > Why can't tuplesort_end do it? > > > > > > Because then I think the parallel workers remove their own files, with > > > tests > > > failing like: > > > > > > +ERROR: could not open temporary file "0.0" from BufFile "0": No such > > > file or directory > > > > > > I look around a bit more and came up with this, which works, but I don't > > > know > > > enough to say if it's right. > > > > I convinced myself this is right, since state->nParticipants==-1 for > > workers. > > Only the leader should do the cleanup. > > > > Added here: > > https://commitfest.postgresql.org/29/2657/
+ if (state->shared && state->shared->workersFinished == state->nParticipants) Isn't it more straight forward to check "state->shared && state->worker == -1"? > I've also investigated this issue. As Thomas mentioned before, this > problem is not specific to parallel index creation. Shared temporary > files could be left if the process is interrupted while deleting the > file as a part of the work of detaching dsm segment. > > To fix this issue, possible solutions would be: > > 1. Like the current patch, we call SharedFileSetDeleteAll() before > DestroyParallelContext() which calls dsm_detach() so that we can make > sure to delete these files while not relying on on_dsm_detach > callback. That way, even if the process is interrupted during that > cleaning, it will clean these files again during transaction abort > (AtEOXact_Parallel() calls dsm_detach()). OTOH a downside would be > that we will end up setting a rule that we need to explicitly call > SharedFileSetDeleteAll(). That seems to be common. We release lock explicitly but it is automatically released on error. Of couse it is slightly different that SharedFileSetOnDetach unconditionally removes the directory but that doesn't matter as far as that behavior doesn't lead to an error. We can skip, as Thomas suggested, the cleanup if not necessary. Looking the comment of SharedFileSetOnDetach: | * everything in them. We can't raise an error on failures, because this runs | * in error cleanup paths. I feel that a function that shouldn't error-out also shouldn't be cancellable. If that's the case, we omit the CHECK_FOR_INTERRUPTS() in walkdir() when elevel is smaller than ERROR. ===== diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index b58502837a..593c23553e 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -3374,7 +3374,9 @@ walkdir(const char *path, { char subpath[MAXPGPATH * 2]; - CHECK_FOR_INTERRUPTS(); + /* omit interrupts while we shouldn't error-out */ + if (elevel >= ERROR) + CHECK_FOR_INTERRUPTS(); if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) ===== > 2. We don't use on_dsm_detach callback to delete the shared file set. > Instead, I wonder if we can delete them at the end of the transaction > by using ResourceOwner mechanism, like we do for non-shared temporary > files cleanup. This idea doesn't have the cons that idea #1 has. OTOH, > the lifetime of the shared file set will change from the parallel > context to the transaction, leading to keep many temporary files until > the transaction end. Also, we would need to rework the handling shared > file set. > > 3. We use on_dsm_detach as well as on_proc_exit callback to delete the > shared file set. It doesn't resolve the root cause but that way, even > if the process didn’t delete it on destroying the parallel context, we > can make sure to delete it on process exit. > > I think #1 is suitable for back branches. For HEAD, I think #2 and #3 > would be better in terms of not setting an implicit rule. Thoughts? As far as we allow dms_detach being canceled, the problem persists anywhat other we do. So #2 and #3 seems a bit too much. It seems to me that #1 + omitting CHECK_FOR_INTERRUPTS() is suitable for all branches. regards. -- Kyotaro Horiguchi NTT Open Source Software Center