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 1mhEJH-0007Jd-59 for pgsql-bugs@arkaria.postgresql.org; Sun, 31 Oct 2021 17:07:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1mhEJF-0007Lf-13 for pgsql-bugs@arkaria.postgresql.org; Sun, 31 Oct 2021 17:07:53 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mhEJE-0007LP-Pg for pgsql-bugs@lists.postgresql.org; Sun, 31 Oct 2021 17:07:52 +0000 Received: from sss.pgh.pa.us ([66.207.139.130]) by magus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1mhEJ9-0000mL-TD for pgsql-bugs@lists.postgresql.org; Sun, 31 Oct 2021 17:07:49 +0000 Received: from sss1.sss.pgh.pa.us (localhost [127.0.0.1]) by sss.pgh.pa.us (8.15.2/8.15.2) with ESMTP id 19VH7glc975809; Sun, 31 Oct 2021 13:07:42 -0400 From: Tom Lane To: =?UTF-8?Q?Juan_Jos=C3=A9_Santamar=C3=ADa_Flecha?= cc: egashira.yusuke@fujitsu.com, PostgreSQL mailing lists Subject: Re: BUG #17254: Crash with 0xC0000409 in pg_stat_statements when pg_stat_tmp\pgss_query_texts.stat exceeded 2GB. In-reply-to: <856857.1635627048@sss.pgh.pa.us> References: <17254-a926c89dc03375c2@postgresql.org> <840436.1635611203@sss.pgh.pa.us> <856857.1635627048@sss.pgh.pa.us> Comments: In-reply-to Tom Lane message dated "Sat, 30 Oct 2021 16:50:48 -0400" MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="----- =_aaaaaaaaaa0" Content-ID: <975781.1635700038.0@sss.pgh.pa.us> Date: Sun, 31 Oct 2021 13:07:42 -0400 Message-ID: <975808.1635700062@sss.pgh.pa.us> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk ------- =_aaaaaaaaaa0 Content-Type: text/plain; charset="us-ascii" Content-ID: <975781.1635700038.1@sss.pgh.pa.us> Content-Transfer-Encoding: quoted-printable I wrote: > =3D?UTF-8?Q?Juan_Jos=3DC3=3DA9_Santamar=3DC3=3DADa_Flecha?=3D writes: >> On Sat, Oct 30, 2021 at 6:26 PM Tom Lane wrote: >>> I think instead, we need to turn the subsequent one-off read() call in= to a >>> loop that reads no more than INT_MAX bytes at a time. It'd be possibl= e >>> to restrict that to Windows, but probably no harm in doing it the same >>> way everywhere. >> Seems reasonable to me, can such a change be back-patched? > Don't see why not. Here's a quick patch for that. I don't have any ability to check it on Windows, but the logic is easy to verify by reducing the arbitrary constant to something small. (I used 1GB, not INT_MAX, because I figured we ought to read in multiples of a filesystem block if possible.) regards, tom lane ------- =_aaaaaaaaaa0 Content-Type: text/x-diff; name="avoid-windows-failure-on-huge-read.patch"; charset="us-ascii" Content-ID: <975781.1635700038.2@sss.pgh.pa.us> Content-Description: avoid-windows-failure-on-huge-read.patch Content-Transfer-Encoding: quoted-printable diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_= stat_statements/pg_stat_statements.c index 07fe0e7cda..726ba59e2b 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -2125,6 +2125,7 @@ qtext_load_file(Size *buffer_size) char *buf; int fd; struct stat stat; + Size nread; = fd =3D OpenTransientFile(PGSS_TEXT_FILE, O_RDONLY | PG_BINARY); if (fd < 0) @@ -2165,23 +2166,35 @@ qtext_load_file(Size *buffer_size) } = /* - * OK, slurp in the file. If we get a short read and errno doesn't get - * set, the reason is probably that garbage collection truncated the fil= e - * since we did the fstat(), so we don't log a complaint --- but we don'= t - * return the data, either, since it's most likely corrupt due to - * concurrent writes from garbage collection. + * OK, slurp in the file. Windows fails if we try to read more than + * INT_MAX bytes at once, and other platforms might not like that either= , + * so read a very large file in 1GB segments. */ - errno =3D 0; - if (read(fd, buf, stat.st_size) !=3D stat.st_size) + nread =3D 0; + while (nread < stat.st_size) { - if (errno) - ereport(LOG, - (errcode_for_file_access(), - errmsg("could not read file \"%s\": %m", - PGSS_TEXT_FILE))); - free(buf); - CloseTransientFile(fd); - return NULL; + int toread =3D Min(1024 * 1024 * 1024, stat.st_size - nread); + + /* + * If we get a short read and errno doesn't get set, the reason is + * probably that garbage collection truncated the file since we did + * the fstat(), so we don't log a complaint --- but we don't return + * the data, either, since it's most likely corrupt due to concurrent + * writes from garbage collection. + */ + errno =3D 0; + if (read(fd, buf + nread, toread) !=3D toread) + { + if (errno) + ereport(LOG, + (errcode_for_file_access(), + errmsg("could not read file \"%s\": %m", + PGSS_TEXT_FILE))); + free(buf); + CloseTransientFile(fd); + return NULL; + } + nread +=3D toread; } = if (CloseTransientFile(fd) !=3D 0) @@ -2189,7 +2202,7 @@ qtext_load_file(Size *buffer_size) (errcode_for_file_access(), errmsg("could not close file \"%s\": %m", PGSS_TEXT_FILE))); = - *buffer_size =3D stat.st_size; + *buffer_size =3D nread; return buf; } = ------- =_aaaaaaaaaa0--