Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jxjxn-0000fA-B5 for pgsql-hackers@arkaria.postgresql.org; Tue, 21 Jul 2020 04:33:11 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1jxjxk-0005lb-Ve for pgsql-hackers@arkaria.postgresql.org; Tue, 21 Jul 2020 04:33:08 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1jxjxk-0005lU-AH for pgsql-hackers@lists.postgresql.org; Tue, 21 Jul 2020 04:33:08 +0000 Received: from mail-io1-xd42.google.com ([2607:f8b0:4864:20::d42]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1jxjxd-0008Db-G5 for pgsql-hackers@postgresql.org; Tue, 21 Jul 2020 04:33:06 +0000 Received: by mail-io1-xd42.google.com with SMTP id p205so19964327iod.8 for ; Mon, 20 Jul 2020 21:33:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :in-reply-to:user-agent; bh=1XFjxe1802Z6nYADiBR44BO8mHT6GZ0j4KoFA6rX7fY=; b=Y1Dzk8ai19v1U8lF5pd5E9DezlEdPiqI+TbxEwWmnGjBtI486eQRBn8yqI3o+/MrWr WpL/dL4kxP/GrE79QYxtB3S9uxCf4D1mHw40ayO3z425r9dPd6Uco6PxQCne++lA4ZWS A+VLpR/CjU0d0x3p1VKmH2vOdl2lWxyiqU4B+NTe2EgaKXvHAY/MdvyWbmHSy9nww1r1 6CdMft0YdK4mbxOqbgFW+O7CXHRNIr491VbrXqqOFIFlp+hhaJIickdl7Bla1gspVND6 FA3E6qFB08h1H3u1o76TEy1iOss2XPzQ7o9G39dhFHK6IKiwMoruTzMsZLCL9pQO2ciW fucg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-disposition:in-reply-to:user-agent; bh=1XFjxe1802Z6nYADiBR44BO8mHT6GZ0j4KoFA6rX7fY=; b=KslzZ3Pa0bUdVDVfvQcMKDClL52UO0VDEaH4mkMk86wxfafJRz9wPxLE/o7qB7470a a0v+sWGxzS+FY1QhbioRFUzvWgzBLdfHl46QEGrUtILeRqKB25wFXFKk0ocBlU+b6HkT zEcUdoTrP4b7N6ql75poQqz/Y7DTfaLaBC9J5Ny0qWiGkO8YG7X8A2i+06phvzDcm0b3 7UCNf2S2J5AQotkxyOmj+4AEE2nvzKTT0gTJXauBVVYjyB94Z3DrQuOJZWKA0D8Kq86x xrMdhqvryyTmYOb+bLCChpxbG8mVBky7LQ/UsjXq1M38DUBSmBa21y9+qx5O0m6X8GjL JGCA== X-Gm-Message-State: AOAM530W/tBSUdaeS+3U9AlIBa7a4KzbseLECD/uPSdUqvFi51UDeXSB Kst3+Wf9USRhUBX6S1h4JvaDxA== X-Google-Smtp-Source: ABdhPJxR5jet14TEjF3GxCkNXfqjPcUFqA8HHYZZJ/3Hb+/3V/KHvnKJL2gGS9vbXH2vy1BJ8H8HXw== X-Received: by 2002:a05:6602:2c08:: with SMTP id w8mr24302370iov.129.1595305980573; Mon, 20 Jul 2020 21:33:00 -0700 (PDT) Received: from pryzbyj.telsasoft (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id i84sm10212278ill.30.2020.07.20.21.32.59 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 20 Jul 2020 21:32:59 -0700 (PDT) Received: by pryzbyj.telsasoft (Postfix, from userid 1000) id 5A235800272; Mon, 20 Jul 2020 23:32:58 -0500 (CDT) Date: Mon, 20 Jul 2020 23:32:58 -0500 From: Justin Pryzby To: Thomas Munro Cc: pgsql-hackers , "Bossart, Nathan" Subject: Re: shared tempfile was not removed on statement_timeout Message-ID: <20200721043258.GE5748@telsasoft.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.9.4 (2018-02-28) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk On Fri, Dec 13, 2019 at 03:03:47PM +1300, Thomas Munro wrote: > On Fri, Dec 13, 2019 at 7:05 AM Justin Pryzby wrote: > > I have a nagios check on ancient tempfiles, intended to catch debris left by > > crashed processes. But triggered on this file: > > > > $ sudo find /var/lib/pgsql/12/data/base/pgsql_tmp -ls > > 142977 4 drwxr-x--- 3 postgres postgres 4096 Dec 12 11:32 /var/lib/pgsql/12/data/base/pgsql_tmp > > 169868 4 drwxr-x--- 2 postgres postgres 4096 Dec 7 01:35 /var/lib/pgsql/12/data/base/pgsql_tmp/pgsql_tmp11025.0.sharedfileset > > 169347 5492 -rw-r----- 1 postgres postgres 5619712 Dec 7 01:35 /var/lib/pgsql/12/data/base/pgsql_tmp/pgsql_tmp11025.0.sharedfileset/0.0 > > 169346 5380 -rw-r----- 1 postgres postgres 5505024 Dec 7 01:35 /var/lib/pgsql/12/data/base/pgsql_tmp/pgsql_tmp11025.0.sharedfileset/1.0 > > > > I found: > > 2019-12-07 01:35:56 | 11025 | postgres | canceling statement due to statement timeout | CLUSTER pg_stat_database_snap USI > > 2019-12-07 01:35:56 | 11025 | postgres | temporary file: path "base/pgsql_tmp/pgsql_tmp11025.0.sharedfileset/2.0", size 5455872 | CLUSTER pg_stat_database_snap USI > > Hmm. I played around with this and couldn't reproduce it, but I > thought of something. What if the statement timeout is reached while > we're in here: > > #0 PathNameDeleteTemporaryDir (dirname=0x7fffffffd010 "base/pgsql_tmp/pgsql_tmp28884.31.sharedfileset") at fd.c:1471 > #1 0x0000000000a32c77 in SharedFileSetDeleteAll (fileset=0x80182e2cc) at sharedfileset.c:177 > #2 0x0000000000a327e1 in SharedFileSetOnDetach (segment=0x80a6e62d8, datum=34385093324) at sharedfileset.c:206 > #3 0x0000000000a365ca in dsm_detach (seg=0x80a6e62d8) at dsm.c:684 > #4 0x000000000061621b in DestroyParallelContext (pcxt=0x80a708f20) at parallel.c:904 > #5 0x00000000005d97b3 in _bt_end_parallel (btleader=0x80fe9b4b0) at nbtsort.c:1473 > #6 0x00000000005d92f0 in btbuild (heap=0x80a7bc4c8, index=0x80a850a50, indexInfo=0x80fec1ab0) at nbtsort.c:340 ... > The CHECK_FOR_INTERRUPTS() inside the walkdir() loop could ereport() > out of there after deleting some but not all of your files, but the > code in dsm_detach() has already popped the callback (which it does > "to avoid infinite error recursion"), so it won't run again on error > cleanup. Hmm. But then... maybe the two log lines you quoted should > be the other way around for that. With inspired from re-reading your messages several times in rapid succession, I was able to reproduce this easily with: --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -3344,6 +3344,7 @@ walkdir(const char *path, struct stat fst; int sret; + usleep(99999); CHECK_FOR_INTERRUPTS(); On Fri, Dec 13, 2019 at 03:49:26PM +1300, Thomas Munro wrote: > Ok, so it looks like we shouldn't be relying on the same code path for > 'happy' and 'error' cleanup. This could probably be fixed with a well > placed explicit call to SharedFileSetDeleteAll() or a new function > SharedFileSetDestroy(), and perhaps a flag in shmem to say it's been > done so the callback doesn't do it again needlessly. I don't think > this problem is specific to parallel index creation. Find below a caveman-approved patch which avoids leaving behind tmpfiles. I'm not sure how to do this cleanly, since: | src/include/utils/tuplesort.h: * Tuplesortstate and Sharedsort are opaque types whose details are not Maybe we need to add a new parameter like: | tuplesort_end(Tuplesortstate *state, bool do_delete_fileset) Arguably, that has the benefit that existing callers *have* to confront whether they should delete the fileset or not. This is such a minor issue that it's unfortunate to force a confrontation over it. -- Justin diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c index efee86784b..f5b0a48d64 100644 --- a/src/backend/access/nbtree/nbtsort.c +++ b/src/backend/access/nbtree/nbtsort.c @@ -511,12 +511,17 @@ _bt_spools_heapscan(Relation heap, Relation index, BTBuildState *buildstate, return reltuples; } +extern void *tuplesort_shared_fileset(Tuplesortstate*); + /* * clean up a spool structure and its substructures. */ static void _bt_spooldestroy(BTSpool *btspool) { + void *fileset = tuplesort_shared_fileset(btspool->sortstate); + if (fileset) + SharedFileSetDeleteAll(fileset); tuplesort_end(btspool->sortstate); pfree(btspool); } @@ -1669,6 +1674,10 @@ _bt_end_parallel(BTLeader *btleader) /* Free last reference to MVCC snapshot, if one was used */ if (IsMVCCSnapshot(btleader->snapshot)) UnregisterSnapshot(btleader->snapshot); + + // SharedFileSetDeleteAll(btleader->sharedsort->fileset); + // SharedFileSetDeleteAll(btleader->sharedsort2->fileset); + DestroyParallelContext(btleader->pcxt); ExitParallelMode(); } diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index 5f6420efb2..f89d42f475 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -3344,6 +3344,7 @@ walkdir(const char *path, struct stat fst; int sret; + usleep(99999); CHECK_FOR_INTERRUPTS(); if (strcmp(de->d_name, ".") == 0 || diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c index 3c49476483..3de9592b78 100644 --- a/src/backend/utils/sort/tuplesort.c +++ b/src/backend/utils/sort/tuplesort.c @@ -1375,6 +1375,11 @@ tuplesort_free(Tuplesortstate *state) MemoryContextReset(state->sortcontext); } +void *tuplesort_shared_fileset(Tuplesortstate *state) +{ + return state->shared ? &state->shared->fileset : NULL; +} + /* * tuplesort_end *