]> granicus.if.org Git - postgresql/commitdiff
Avoid "invalid memory alloc request size" while reading pg_stat_activity.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 7 May 2019 15:41:37 +0000 (11:41 -0400)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 7 May 2019 15:41:37 +0000 (11:41 -0400)
On a 64-bit machine, if you set track_activity_query_size and
max_connections such that their product exceeds 1GB, shared memory
setup will still succeed (given enough RAM), but attempts to read
pg_stat_activity fail with "invalid memory alloc request size".
Work around that by using MemoryContextAllocHuge to allocate the
local copy of the activity strings.  Using the "huge" API costs us
nothing extra in normal cases, and it seems better than throwing
an error and/or explaining to people why they can't do this.

This situation seems insanely profligate today, but who knows what
people will consider normal in ten or twenty years?  So let's fix it
in HEAD but not worry about a back-patch.

Per report from James Tomson.

Discussion: https://postgr.es/m/1CFDCCD6-B268-48D8-85C8-400D2790B2C3@pushd.com

src/backend/postmaster/pgstat.c

index 4cfae15d3a9a90d6da41b62047e7d4181393a139..64986b17c871e67e44e189b2c3dce480b9713270 100644 (file)
@@ -3319,6 +3319,14 @@ pgstat_read_current_status(void)
 
        pgstat_setup_memcxt();
 
+       /*
+        * Allocate storage for local copy of state data.  We can presume that
+        * none of these requests overflow size_t, because we already calculated
+        * the same values using mul_size during shmem setup.  However, with
+        * probably-silly values of pgstat_track_activity_query_size and
+        * max_connections, the localactivity buffer could exceed 1GB, so use
+        * "huge" allocation for that one.
+        */
        localtable = (LocalPgBackendStatus *)
                MemoryContextAlloc(pgStatLocalContext,
                                                   sizeof(LocalPgBackendStatus) * NumBackendStatSlots);
@@ -3329,8 +3337,8 @@ pgstat_read_current_status(void)
                MemoryContextAlloc(pgStatLocalContext,
                                                   NAMEDATALEN * NumBackendStatSlots);
        localactivity = (char *)
-               MemoryContextAlloc(pgStatLocalContext,
-                                                  pgstat_track_activity_query_size * NumBackendStatSlots);
+               MemoryContextAllocHuge(pgStatLocalContext,
+                                                          pgstat_track_activity_query_size * NumBackendStatSlots);
 #ifdef USE_SSL
        localsslstatus = (PgBackendSSLStatus *)
                MemoryContextAlloc(pgStatLocalContext,