public inbox for [email protected]  
help / color / mirror / Atom feed
From: Matheus Alcantara <[email protected]>
To: Glauber Batista <[email protected]>
To: [email protected]
Subject: Re: Autoprewarm workers terminated due to a segmentation fault
Date: Tue, 09 Jun 2026 18:06:09 -0300
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAO+_mTQgQyTYwDh=U8iTnsDmOGyWsZJjUV31SmEYwmw6_xY6Bw@mail.gmail.com>
References: <CAO+_mTQgQyTYwDh=U8iTnsDmOGyWsZJjUV31SmEYwmw6_xY6Bw@mail.gmail.com>

Hi,

On Tue Jun 9, 2026 at 3:37 PM -03, Glauber Batista wrote:
> I have an issue with the autoprewarm workers segfaulting during the service
> restart. Sometimes, it successfully restarts after a few tries, but usually
> I need to remove the autoprewarm.blocks file. My setup consists of a
> primary server with two replicas and all of them present the same issue. I
> have been using this setup for several years with no issues, but since I
> upgraded to Postgres 18 I'm having it. This is a production database.
>
> Details:
>
> [ ... ] 
>
> All that said, it seems there's a missing guard-clause at line 649. I
> didn't spend much time reading the code, but it's clearly accessing a
> position in the array that is not allocated.
>

Thank you for the report!

I've managed to reproduce the issue with the following:

create table test_warm (id int, data text);
-- insert enough rows to generate too many pages on an index
insert into test_warm select g, repeat('a', 100) from generate_series(1, 5000000) g;
create index warm_idx on test_warm(id);

-- force read the index entirely into shared_buffers
select count(*) from test_warm where id > 0;

Then pg_ctl stop and pg_ctl start will start failing with the following logs:

2026-06-09 17:47:40.924 -03 [23025] LOG:  shutting down
2026-06-09 17:47:40.925 -03 [23025] LOG:  checkpoint starting: shutdown fast
2026-06-09 17:47:41.033 -03 [23022] LOG:  database system is shut down
2026-06-09 17:47:49.830 -03 [23172] LOG:  starting PostgreSQL 19beta1 on aarch64-darwin, compiled by clang-17.0.0, 64-bit
2026-06-09 17:47:49.842 -03 [23172] LOG:  database system is ready to accept connections
2026-06-09 17:47:49.917 -03 [23172] LOG:  background worker "autoprewarm worker" (PID 23182) was terminated by signal 11: Segmentation fault: 11
2026-06-09 17:47:49.917 -03 [23172] LOG:  terminating any other active server processes
2026-06-09 17:47:49.918 -03 [23172] LOG:  all server processes terminated; reinitializing

Wondering if the following would be enough?

  /* Advance i past all the blocks just prewarmed. */
  i = p.pos;
+ if (i >= apw_state->prewarm_stop_idx)
+         break;
+
  blk = block_info[i];


With this change on a fresh start I got very similar shared hit buffers
on the first and second execution, so I think that the
autoprewarm.blocks was reloaded successfully?

postgres=# explain(analyze, costs off, timing off, summary off) select count(*) from test_warm where id > 0;
                                    QUERY PLAN
-----------------------------------------------------------------------------------
 Finalize Aggregate (actual rows=1.00 loops=1)
   Buffers: shared hit=15965 read=70242
   ->  Gather (actual rows=3.00 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         Buffers: shared hit=15965 read=70242
         ->  Partial Aggregate (actual rows=1.00 loops=3)
               Buffers: shared hit=15965 read=70242
               ->  Parallel Seq Scan on test_warm (actual rows=1666666.67 loops=3)
                     Filter: (id > 0)
                     Buffers: shared hit=15965 read=70242

postgres=# explain(analyze, costs off, timing off, summary off) SELECT count(*) FROM test_warm WHERE id > 0;
                                    QUERY PLAN
-----------------------------------------------------------------------------------
 Finalize Aggregate (actual rows=1.00 loops=1)
   Buffers: shared hit=15970 read=70237
   ->  Gather (actual rows=3.00 loops=1)
         Workers Planned: 2
         Workers Launched: 2
         Buffers: shared hit=15970 read=70237
         ->  Partial Aggregate (actual rows=1.00 loops=3)
               Buffers: shared hit=15970 read=70237
               ->  Parallel Seq Scan on test_warm (actual rows=1666666.67 loops=3)
                     Filter: (id > 0)
                     Buffers: shared hit=15970 read=70237


Thoughts?

--
Matheus Alcantara
EDB: https://www.enterprisedb.com

From 6a3e3e26c0328e15fc47091684143dc5bb8ef6fc Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 17:59:20 -0300
Subject: [PATCH] Fix out-of-bounds access in autoprewarm worker

The read stream callback apw_read_stream_next_block() advances p->pos
through the block_info array until it reaches a block belonging to a
different relation/fork or hits prewarm_stop_idx. When the stream
finishes processing all blocks for a fork, p.pos may equal
prewarm_stop_idx which cause a segfault.

Add a bounds check before accessing block_info[i] to prevent the crash.

Author: Matheus Alcantara <[email protected]>
Reported-by: Glauber Batista <[email protected]>
Discussion: https://www.postgresql.org/message-id/CAO%2B_mTQgQyTYwDh%3DU8iTnsDmOGyWsZJjUV31SmEYwmw6_xY6Bw%40mail...
---
 contrib/pg_prewarm/autoprewarm.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index ba0bc8e6d4a..a77e52c59ea 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -643,8 +643,15 @@ autoprewarm_database_main(Datum main_arg)
 
 			read_stream_end(stream);
 
-			/* Advance i past all the blocks just prewarmed. */
+			/*
+			 * Advance i past all the blocks just prewarmed. The read stream
+			 * callback may have advanced p.pos to prewarm_stop_idx, so we
+			 * must check bounds before accessing block_info[i].
+			 */
 			i = p.pos;
+			if (i >= apw_state->prewarm_stop_idx)
+				break;
+
 			blk = block_info[i];
 		}
 
-- 
2.50.1 (Apple Git-155)



Attachments:

  [text/plain] 0001-Fix-out-of-bounds-access-in-autoprewarm-worker.patch (1.6K, ../[email protected]/2-0001-Fix-out-of-bounds-access-in-autoprewarm-worker.patch)
  download | inline diff:
From 6a3e3e26c0328e15fc47091684143dc5bb8ef6fc Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 17:59:20 -0300
Subject: [PATCH] Fix out-of-bounds access in autoprewarm worker

The read stream callback apw_read_stream_next_block() advances p->pos
through the block_info array until it reaches a block belonging to a
different relation/fork or hits prewarm_stop_idx. When the stream
finishes processing all blocks for a fork, p.pos may equal
prewarm_stop_idx which cause a segfault.

Add a bounds check before accessing block_info[i] to prevent the crash.

Author: Matheus Alcantara <[email protected]>
Reported-by: Glauber Batista <[email protected]>
Discussion: https://www.postgresql.org/message-id/CAO%2B_mTQgQyTYwDh%3DU8iTnsDmOGyWsZJjUV31SmEYwmw6_xY6Bw%40mail.gmail.com
---
 contrib/pg_prewarm/autoprewarm.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index ba0bc8e6d4a..a77e52c59ea 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -643,8 +643,15 @@ autoprewarm_database_main(Datum main_arg)
 
 			read_stream_end(stream);
 
-			/* Advance i past all the blocks just prewarmed. */
+			/*
+			 * Advance i past all the blocks just prewarmed. The read stream
+			 * callback may have advanced p.pos to prewarm_stop_idx, so we
+			 * must check bounds before accessing block_info[i].
+			 */
 			i = p.pos;
+			if (i >= apw_state->prewarm_stop_idx)
+				break;
+
 			blk = block_info[i];
 		}
 
-- 
2.50.1 (Apple Git-155)



view thread (10+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: Autoprewarm workers terminated due to a segmentation fault
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox