public inbox for [email protected]
help / color / mirror / Atom feedAutoprewarm workers terminated due to a segmentation fault
10+ messages / 4 participants
[nested] [flat]
* Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-09 18:37 Glauber Batista <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Glauber Batista @ 2026-06-09 18:37 UTC (permalink / raw)
To: [email protected]
Hello,
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:
Postgres Version: PostgreSQL 18.3 on aarch64-unknown-linux-gnu, compiled by
gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0, 64-bit
This is the related settings I'm using in postgresql.conf
```
shared_preload_libraries = 'pg_stat_statements,pg_prewarm'
pg_prewarm.autoprewarm = True
pg_prewarm.autoprewarm_interval = 300s
```
I'm using systemd to manage Postgres, but it also happens if I start
postgres using `pg_ctl`. So I ruled out a systemd issue.
This is the error message I'm seeing.
```
LOG: restored log file "000000010000079200000015" from archive
LOG: consistent recovery state reached at 792/15A586C8
LOG: database system is ready to accept read-only connections
LOG: restored log file "000000010000079200000016" from archive
LOG: restored log file "000000010000079200000017" from archive
LOG: background worker "autoprewarm worker" (PID 2350) was terminated by
signal 11: Segmentation fault
LOG: terminating any other active server processes
LOG: all server processes terminated; reinitializing
LOG: database system was interrupted while in recovery at log time
2026-06-09 17:34:19 UTC
HINT: If this has occurred more than once some data might be corrupted and
you might need to choose an earlier recovery target.
LOG: restored log file "00000001000007920000000D" from archive
LOG: restored log file "0000000100000791000000F8" from archive
LOG: entering standby mode
LOG: redo starts at 791/F804CB38
LOG: database system is ready to accept read-only connections
LOG: restored log file "0000000100000791000000F9" from archive
LOG: restored log file "0000000100000791000000FA" from archive
LOG: restored log file "0000000100000791000000FB" from archive
LOG: background worker "autoprewarm worker" (PID 2522) was terminated by
signal 11: Segmentation fault
LOG: terminating any other active server processes
FATAL: could not restore file "0000000100000791000000FC" from archive:
child process was terminated by signal 3: Quit
LOG: all server processes terminated; reinitializing
LOG: database system was interrupted while in recovery at log time
2026-06-09 17:34:19 UTC
HINT: If this has occurred more than once some data might be corrupted and
you might need to choose an earlier recovery target.
LOG: restored log file "00000001000007920000000D" from archive
LOG: restored log file "0000000100000791000000F8" from archive
LOG: entering standby mode
```
Changing the debug level to DEBUG1 didn't show anything useful, so I'm not
pasting it here.
At first, I thought it could be somehow related to this bug:
https://www.datadoghq.com/blog/engineering/unraveling-a-postgres-segfault/,
but investigating a bit it does not seem to be the case. Either way, I
compiled Postgres again using CFLAGS="-O0 -g -fno-strict-aliasing" to check
if it was something related to the code optimization for ARM64, but the
issue persisted.
Then, I used gdb to get the core file. Since it has been quite some time
since I didn't debug anything written in C/C++, I used Claude to guide me.
Here's some info:
```
(gdb) frame 0
#0 0x0000f5a0c6003854 in autoprewarm_database_main (main_arg=0) at
autoprewarm.c:649
649 blk = block_info[i];
(gdb) list
644
645 read_stream_end(stream);
646
647 /* Advance i past all the blocks just prewarmed. */
648 i = p.pos;
649 blk = block_info[i];
650 }
651
652 relation_close(rel, AccessShareLock);
653 CommitTransactionCommand();
(gdb) p *block_info
$1 = {database = 0, tablespace = 0, filenumber = 0, forknum = MAIN_FORKNUM,
blocknum = 0}
(gdb) p p
$2 = {block_info = 0xf5a07f600000, pos = 131072, tablespace = 1663,
filenumber = 28197, forknum = MAIN_FORKNUM, nblocks = 65329}
(gdb) p stream
$3 = (ReadStream *) 0xb82a946671f0
(gdb) p *(ReadStream *) stream
$4 = {max_ios = 0, io_combine_limit = 0, ios_in_progress = 0, queue_size =
0, max_pinned_buffers = 225, forwarded_buffers = 0, pinned_buffers = 0,
distance = 1,
initialized_buffers = 9, read_buffers_flags = 0, sync_mode = false,
batch_mode = true, advice_enabled = false, temporary = false,
buffered_blocknum = 4294967295,
callback = 0xf5a0c600330c <apw_read_stream_next_block>,
callback_private_data = 0xfffff758cea8, seq_blocknum = 2403,
seq_until_processed = 4294967295,
pending_read_blocknum = 2403, pending_read_nblocks = 0,
per_buffer_data_size = 0, per_buffer_data = 0x0, ios = 0xb82a94667618,
oldest_io_index = 8, next_io_index = 8,
fast_path = false, oldest_buffer_index = 9, next_buffer_index = 9,
buffers = 0xb82a94667254}
(gdb) p p.pos
$5 = 131072
(gdb) p p.nblocks
$6 = 65329
(gdb) p apw_state->prewarm_stop_idx
$7 = 0
(gdb) p apw_state->prewarm_start_idx
$8 = 0
(gdb) p block_info[131072]
Cannot access memory at address 0xf5a07f880000
(gdb) p &block_info[131072]
$9 = (BlockInfoRecord *) 0xf5a07f880000
(gdb) p block_info[131071]
$10 = {database = 0, tablespace = 0, filenumber = 0, forknum =
MAIN_FORKNUM, blocknum = 0}
(gdb) p block_info[131070]
$11 = {database = 0, tablespace = 0, filenumber = 0, forknum =
MAIN_FORKNUM, blocknum = 0}
(gdb) p block_info[1]
$12 = {database = 0, tablespace = 0, filenumber = 0, forknum =
MAIN_FORKNUM, blocknum = 0}
(gdb) p apw_state->prewarmed_blocks
$13 = 0
(gdb) p *apw_state
$14 = {lock = {tranche = 0, state = {value = 0}, waiters = {head = 0, tail
= 0}}, bgworker_pid = 0, pid_using_dumpfile = 0, block_info_handle = 0,
database = 0,
prewarm_start_idx = 0, prewarm_stop_idx = 0, prewarmed_blocks = 0}
(gdb) info line autoprewarm.c:649
Line 649 of "autoprewarm.c" starts at address 0xf5a0c600382c
<autoprewarm_database_main+936> and ends at 0xf5a0c600384c
<autoprewarm_database_main+968>.
(gdb) list autoprewarm.c:640,660
640 {
641 apw_state->prewarmed_blocks++;
642 ReleaseBuffer(buf);
643 }
644
645 read_stream_end(stream);
646
647 /* Advance i past all the blocks just prewarmed. */
648 i = p.pos;
649 blk = block_info[i];
650 }
651
652 relation_close(rel, AccessShareLock);
653 CommitTransactionCommand();
654 }
655
656 dsm_detach(seg);
657 }
658
659 /*
660 * Dump information on blocks in shared buffers. We use a text
format here
```
I found out that some parts of the autoprewarm were re-written recently
here:
https://www.postgresql.org/message-id/flat/CAN55FZ3n8Gd%2BhajbL%3D5UkGzu_aHGRqnn%2BxktXq2fuds%3D1AOR...
and I think it could be related, given the data present in the dump.
Also, I inspected my data to ensure it was not the culprit. I got the
database and filenumber from `bt full` and run the following queries.
```
blk = {database = 23583, tablespace = 1663, filenumber = 28197, forknum =
MAIN_FORKNUM, blocknum = 49}
```
So I queried the database (23583) and the filenumber (28197) using
```
SELECT datname FROM pg_database WHERE oid = 23583;
\c <datname>
SELECT relname, relkind, relpages, pg_relation_filenode(oid) AS filenode
FROM pg_class
WHERE pg_relation_filenode(oid) = 28197;
```
and it returned
```
relname | relkind | relpages | filenode
--------------+---------+----------+----------
lccss_cc_idx | i | 64805 | 28197
```
So I think it's not stale data or shrunk relation caused by VACUUM,
TRUNCATE, etc.
I'm only reporting with the latest data I collected, but this issue has
been happening since April, when I upgraded the database.
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.
Let me know if any extra information is needed.
Best,
Glauber Cassiano Batista
#0 0x0000f5a0c6003854 in autoprewarm_database_main (main_arg=0) at autoprewarm.c:649
stream = 0xb82a946671f0
buf = 0
forknum = MAIN_FORKNUM
nblocks = 65329
p = {block_info = 0xf5a07f600000, pos = 131072, tablespace = 1663, filenumber = 28197, forknum = MAIN_FORKNUM, nblocks = 65329}
tablespace = 1663
filenumber = 28197
reloid = 28197
rel = 0xf5a07f19f448
block_info = 0xf5a07f600000
i = 131072
blk = {database = 23583, tablespace = 1663, filenumber = 28197, forknum = MAIN_FORKNUM, blocknum = 49}
seg = 0xb82a945b6608
__func__ = "autoprewarm_database_main"
#1 0x0000b82a910f6a00 in BackgroundWorkerMain (startup_data=0xb82a945e9a40, startup_data_len=1472) at bgworker.c:843
local_sigjmp_buf = {{__jmpbuf = {202493017379120, 3, 202492969070024, 202492960511404, 281474831538824, 270070918785880, 0, 270070918787072, 202492969070024, 0,
281474831536192, 14748075884817566773, 202492965626472, 14748153214131628973, 0, 0, 0, 0, 0, 0, 0, 0}, __mask_was_saved = 1, __saved_mask = {__val = {
18446744066192964099, 281474831536128, 270070903983828, 281474831536160, 281474831536192, 281474831536192, 281474831536176, 4294967288,
7799472315257153536, 281474831536192, 202492965149164, 202493017379120, 3, 281474831536192, 202492965149140, 281474831536192}}}}
worker = 0xb82a945ed238
entrypt = 0xf5a0c6003484 <autoprewarm_database_main>
__func__ = "BackgroundWorkerMain"
#2 0x0000b82a910fb024 in postmaster_child_launch (child_type=B_BG_WORKER, child_slot=1039, startup_data=0xb82a945e9a40, startup_data_len=1472, client_sock=0x0)
at launch_backend.c:290
pid = 0
#3 0x0000b82a911031a0 in StartBackgroundWorker (rw=0xb82a945e9a40) at postmaster.c:4157
bn = 0xb82a945c0800
worker_pid = 65535
__func__ = "StartBackgroundWorker"
#4 0x0000b82a91103490 in maybe_start_bgworkers () at postmaster.c:4323
rw = 0xb82a945e9a40
num_launched = 0
now = 0
iter = {cur = 0xb82a945ea018, next = 0xb82a945600a0, end = 0xb82a91804de8 <BackgroundWorkerList>}
#5 0x0000b82a91101cf4 in LaunchMissingBackgroundProcesses () at postmaster.c:3397
No locals.
#6 0x0000b82a910ff308 in ServerLoop () at postmaster.c:1717
now = 1781027919
last_lockfile_recheck_time = 1781027882
last_touch_time = 1781027381
events = {{pos = 0, events = 1, fd = -1, user_data = 0x0}, {pos = 0, events = 0, fd = -32, user_data = 0x0}, {pos = -934847836, events = 62880, fd = -145173904,
user_data = 0xf5a0c84767dc <__GI___libc_malloc+540>}, {pos = -933691392, events = 62880, fd = 312, user_data = 0x8030}, {pos = -920021152, events = 62880,
fd = -933666816, user_data = 0xf5a0c9299898}, {pos = 0, events = 0, fd = -919752704, user_data = 0xb82a917dadc8}, {pos = 0, events = 0, fd = -145171864,
user_data = 0x61642f67702f2220}, {pos = -145173856, events = 65535, fd = 1382377472, user_data = 0xfffff758d2e0}, {pos = -934842472, events = 62880,
fd = -1805883088, user_data = 0xf5a0c9299760}, {pos = -145173792, events = 65535, fd = -934842472, user_data = 0xfffff758d2e0}, {pos = -934842472,
events = 62880, fd = -1805883088, user_data = 0xf5a0c9299760}, {pos = -933665040, events = 62880, fd = 256, user_data = 0xfffff758d320}, {pos = -934688024,
events = 62880, fd = 10, user_data = 0x3}, {pos = -1854034488, events = 47146, fd = -1862593108, user_data = 0xfffff758da88}, {pos = -934687276,
events = 62880, fd = -145173696, user_data = 0xb82a911aef58 <FreeDesc+124>}, {pos = -145173696, events = 65535, fd = -1860505768, user_data = 0xfffff758d370}, {
pos = -1860504272, events = 47146, fd = -145173664, user_data = 0xb82a94560d20}, {pos = -145172512, events = 65535, fd = -1860502132,
user_data = 0xfffff758d380}, {pos = -934848652, events = 62880, fd = -145173520, user_data = 0xf5a0c84767dc <__GI___libc_malloc+540>}, {pos = -933691392,
events = 62880, fd = 312, user_data = 0x1000}, {pos = -920021152, events = 62880, fd = -933666816, user_data = 0xf5a0c9299898}, {pos = 0, events = 0, fd = 1,
user_data = 0x0}, {pos = 0, events = 0, fd = -145173424, user_data = 0xf5a0c84767dc <__GI___libc_malloc+540>}, {pos = -145173408, events = 65535,
fd = -934844452, user_data = 0xf5a0c8590000 <current_rtmin>}, {pos = 312, events = 0, fd = 2048, user_data = 0xf5a0c9299760}, {pos = -933666816, events = 3,
fd = 7, user_data = 0xb82a945c9170}, {pos = -1805872744, events = 47146, fd = -1854034488, user_data = 0x28}, {pos = -145173344, events = 65535,
fd = -1857808328, user_data = 0xfffff758d4a0}, {pos = -1857808604, events = 7, fd = 1024, user_data = 0x400}, {pos = -145173360, events = 65535,
fd = -934859544, user_data = 0xfffff758d4c0}, {pos = -934854228, events = 62880, fd = -1805883088, user_data = 0xf5a0c8590a50 <main_arena>}, {pos = 2064,
events = 0, fd = -1805881024, user_data = 0xfffff758d500}, {pos = -934842472, events = 62880, fd = -1805883088, user_data = 0xf5a0c9299760}, {pos = -933665040,
events = 62880, fd = 256, user_data = 0x0}, {pos = -934950144, events = 62880, fd = -145172928, user_data = 0xf5a0c84a1d00 <__libc_fork+432>}, {pos = 0,
events = 0, fd = 3, user_data = 0xfffff758d660}, {pos = -934667008, events = 62880, fd = 1, user_data = 0x3}, {pos = -920021152, events = 62880, fd = 0,
user_data = 0xfffff758da88}, {pos = -919753896, events = 62880, fd = 0, user_data = 0xf5a0c92db000 <_rtld_global>}, {pos = -145172896, events = 65535,
fd = -934667360, user_data = 0xb82a945c5ab0}, {pos = 0, events = 0, fd = 88, user_data = 0xb82a945c5b60}, {pos = -145173072, events = 65535, fd = -934859544,
user_data = 0xfffff758d5e0}, {pos = -934854228, events = 62880, fd = -1805876912, user_data = 0xf5a0c8590a50 <main_arena>}, {pos = 4112, events = 0,
fd = -1805872800, user_data = 0xfffff758d640}, {pos = -934938864, events = 62880, fd = 0, user_data = 0xf5a0c8592000 <initial+416>}, {pos = -145172896,
events = 65535, fd = -934938864, user_data = 0x0}, {pos = -933683200, events = 62880, fd = -920023008, user_data = 0xb82a90fb15ac <main>}, {pos = 0,
events = 0, fd = -934945152, user_data = 0x0}, {pos = 0, events = 47146, fd = 0, user_data = 0x6c3d4abf52656800}, {pos = -145172624, events = 65535,
fd = -1861243872, user_data = 0xfffff758da68}, {pos = 3, events = 0, fd = -1854034488, user_data = 0xb82a90fb15ac <main>}, {pos = -145171832, events = 65535,
fd = 1382377472, user_data = 0xfffff758d6b0}, {pos = -935211684, events = 62880, fd = -145172624, user_data = 0xb82a910face8 <fork_process+268>}, {
pos = -145172720, events = 65535, fd = 4194304, user_data = 0xfffff758da68}, {pos = -1806469200, events = 47146, fd = -1806469000, user_data = 0x400000}, {
pos = 1024, events = 0, fd = -1806469200, user_data = 0xb82a91836fe8 <context_freelists+16>}, {pos = 19, events = 13, fd = -145172688,
user_data = 0xb82a91407be4 <errstart+264>}, {pos = 1024, events = 0, fd = 19, user_data = 0xfffff758d750}, {pos = -1858044956, events = 47146, fd = 0,
user_data = 0xd945c11b0}, {pos = -145172608, events = 65535, fd = -1861234604, user_data = 0x0}, {pos = 1382377472, events = 1815956159, fd = -145172608,
user_data = 0xb82a910faedc <postmaster_child_launch+72>}, {pos = -145172544, events = 65535, fd = -1861210828, user_data = 0x0}, {pos = 0, events = 0, fd = 0,
user_data = 0x200000442}, {pos = -145172304, events = 65535, fd = -1861227892, user_data = 0xffff00000000}}
nevents = 1
__func__ = "ServerLoop"
#7 0x0000b82a910fea90 in PostmasterMain (argc=3, argv=0xb82a945195b0) at postmaster.c:1400
opt = -1
status = 0
userDoption = 0xb82a9455e4d0 "/pg/data"
listen_addr_saved = true
output_config_variable = 0x0
__func__ = "PostmasterMain"
#8 0x0000b82a90fb1970 in main (argc=3, argv=0xb82a945195b0) at main.c:227
do_check_root = true
dispatch_option = DISPATCH_POSTMASTER
Attachments:
[text/plain] bt_full.txt (8.1K, ../../CAO+_mTQgQyTYwDh=U8iTnsDmOGyWsZJjUV31SmEYwmw6_xY6Bw@mail.gmail.com/3-bt_full.txt)
download | inline:
#0 0x0000f5a0c6003854 in autoprewarm_database_main (main_arg=0) at autoprewarm.c:649
stream = 0xb82a946671f0
buf = 0
forknum = MAIN_FORKNUM
nblocks = 65329
p = {block_info = 0xf5a07f600000, pos = 131072, tablespace = 1663, filenumber = 28197, forknum = MAIN_FORKNUM, nblocks = 65329}
tablespace = 1663
filenumber = 28197
reloid = 28197
rel = 0xf5a07f19f448
block_info = 0xf5a07f600000
i = 131072
blk = {database = 23583, tablespace = 1663, filenumber = 28197, forknum = MAIN_FORKNUM, blocknum = 49}
seg = 0xb82a945b6608
__func__ = "autoprewarm_database_main"
#1 0x0000b82a910f6a00 in BackgroundWorkerMain (startup_data=0xb82a945e9a40, startup_data_len=1472) at bgworker.c:843
local_sigjmp_buf = {{__jmpbuf = {202493017379120, 3, 202492969070024, 202492960511404, 281474831538824, 270070918785880, 0, 270070918787072, 202492969070024, 0,
281474831536192, 14748075884817566773, 202492965626472, 14748153214131628973, 0, 0, 0, 0, 0, 0, 0, 0}, __mask_was_saved = 1, __saved_mask = {__val = {
18446744066192964099, 281474831536128, 270070903983828, 281474831536160, 281474831536192, 281474831536192, 281474831536176, 4294967288,
7799472315257153536, 281474831536192, 202492965149164, 202493017379120, 3, 281474831536192, 202492965149140, 281474831536192}}}}
worker = 0xb82a945ed238
entrypt = 0xf5a0c6003484 <autoprewarm_database_main>
__func__ = "BackgroundWorkerMain"
#2 0x0000b82a910fb024 in postmaster_child_launch (child_type=B_BG_WORKER, child_slot=1039, startup_data=0xb82a945e9a40, startup_data_len=1472, client_sock=0x0)
at launch_backend.c:290
pid = 0
#3 0x0000b82a911031a0 in StartBackgroundWorker (rw=0xb82a945e9a40) at postmaster.c:4157
bn = 0xb82a945c0800
worker_pid = 65535
__func__ = "StartBackgroundWorker"
#4 0x0000b82a91103490 in maybe_start_bgworkers () at postmaster.c:4323
rw = 0xb82a945e9a40
num_launched = 0
now = 0
iter = {cur = 0xb82a945ea018, next = 0xb82a945600a0, end = 0xb82a91804de8 <BackgroundWorkerList>}
#5 0x0000b82a91101cf4 in LaunchMissingBackgroundProcesses () at postmaster.c:3397
No locals.
#6 0x0000b82a910ff308 in ServerLoop () at postmaster.c:1717
now = 1781027919
last_lockfile_recheck_time = 1781027882
last_touch_time = 1781027381
events = {{pos = 0, events = 1, fd = -1, user_data = 0x0}, {pos = 0, events = 0, fd = -32, user_data = 0x0}, {pos = -934847836, events = 62880, fd = -145173904,
user_data = 0xf5a0c84767dc <__GI___libc_malloc+540>}, {pos = -933691392, events = 62880, fd = 312, user_data = 0x8030}, {pos = -920021152, events = 62880,
fd = -933666816, user_data = 0xf5a0c9299898}, {pos = 0, events = 0, fd = -919752704, user_data = 0xb82a917dadc8}, {pos = 0, events = 0, fd = -145171864,
user_data = 0x61642f67702f2220}, {pos = -145173856, events = 65535, fd = 1382377472, user_data = 0xfffff758d2e0}, {pos = -934842472, events = 62880,
fd = -1805883088, user_data = 0xf5a0c9299760}, {pos = -145173792, events = 65535, fd = -934842472, user_data = 0xfffff758d2e0}, {pos = -934842472,
events = 62880, fd = -1805883088, user_data = 0xf5a0c9299760}, {pos = -933665040, events = 62880, fd = 256, user_data = 0xfffff758d320}, {pos = -934688024,
events = 62880, fd = 10, user_data = 0x3}, {pos = -1854034488, events = 47146, fd = -1862593108, user_data = 0xfffff758da88}, {pos = -934687276,
events = 62880, fd = -145173696, user_data = 0xb82a911aef58 <FreeDesc+124>}, {pos = -145173696, events = 65535, fd = -1860505768, user_data = 0xfffff758d370}, {
pos = -1860504272, events = 47146, fd = -145173664, user_data = 0xb82a94560d20}, {pos = -145172512, events = 65535, fd = -1860502132,
user_data = 0xfffff758d380}, {pos = -934848652, events = 62880, fd = -145173520, user_data = 0xf5a0c84767dc <__GI___libc_malloc+540>}, {pos = -933691392,
events = 62880, fd = 312, user_data = 0x1000}, {pos = -920021152, events = 62880, fd = -933666816, user_data = 0xf5a0c9299898}, {pos = 0, events = 0, fd = 1,
user_data = 0x0}, {pos = 0, events = 0, fd = -145173424, user_data = 0xf5a0c84767dc <__GI___libc_malloc+540>}, {pos = -145173408, events = 65535,
fd = -934844452, user_data = 0xf5a0c8590000 <current_rtmin>}, {pos = 312, events = 0, fd = 2048, user_data = 0xf5a0c9299760}, {pos = -933666816, events = 3,
fd = 7, user_data = 0xb82a945c9170}, {pos = -1805872744, events = 47146, fd = -1854034488, user_data = 0x28}, {pos = -145173344, events = 65535,
fd = -1857808328, user_data = 0xfffff758d4a0}, {pos = -1857808604, events = 7, fd = 1024, user_data = 0x400}, {pos = -145173360, events = 65535,
fd = -934859544, user_data = 0xfffff758d4c0}, {pos = -934854228, events = 62880, fd = -1805883088, user_data = 0xf5a0c8590a50 <main_arena>}, {pos = 2064,
events = 0, fd = -1805881024, user_data = 0xfffff758d500}, {pos = -934842472, events = 62880, fd = -1805883088, user_data = 0xf5a0c9299760}, {pos = -933665040,
events = 62880, fd = 256, user_data = 0x0}, {pos = -934950144, events = 62880, fd = -145172928, user_data = 0xf5a0c84a1d00 <__libc_fork+432>}, {pos = 0,
events = 0, fd = 3, user_data = 0xfffff758d660}, {pos = -934667008, events = 62880, fd = 1, user_data = 0x3}, {pos = -920021152, events = 62880, fd = 0,
user_data = 0xfffff758da88}, {pos = -919753896, events = 62880, fd = 0, user_data = 0xf5a0c92db000 <_rtld_global>}, {pos = -145172896, events = 65535,
fd = -934667360, user_data = 0xb82a945c5ab0}, {pos = 0, events = 0, fd = 88, user_data = 0xb82a945c5b60}, {pos = -145173072, events = 65535, fd = -934859544,
user_data = 0xfffff758d5e0}, {pos = -934854228, events = 62880, fd = -1805876912, user_data = 0xf5a0c8590a50 <main_arena>}, {pos = 4112, events = 0,
fd = -1805872800, user_data = 0xfffff758d640}, {pos = -934938864, events = 62880, fd = 0, user_data = 0xf5a0c8592000 <initial+416>}, {pos = -145172896,
events = 65535, fd = -934938864, user_data = 0x0}, {pos = -933683200, events = 62880, fd = -920023008, user_data = 0xb82a90fb15ac <main>}, {pos = 0,
events = 0, fd = -934945152, user_data = 0x0}, {pos = 0, events = 47146, fd = 0, user_data = 0x6c3d4abf52656800}, {pos = -145172624, events = 65535,
fd = -1861243872, user_data = 0xfffff758da68}, {pos = 3, events = 0, fd = -1854034488, user_data = 0xb82a90fb15ac <main>}, {pos = -145171832, events = 65535,
fd = 1382377472, user_data = 0xfffff758d6b0}, {pos = -935211684, events = 62880, fd = -145172624, user_data = 0xb82a910face8 <fork_process+268>}, {
pos = -145172720, events = 65535, fd = 4194304, user_data = 0xfffff758da68}, {pos = -1806469200, events = 47146, fd = -1806469000, user_data = 0x400000}, {
pos = 1024, events = 0, fd = -1806469200, user_data = 0xb82a91836fe8 <context_freelists+16>}, {pos = 19, events = 13, fd = -145172688,
user_data = 0xb82a91407be4 <errstart+264>}, {pos = 1024, events = 0, fd = 19, user_data = 0xfffff758d750}, {pos = -1858044956, events = 47146, fd = 0,
user_data = 0xd945c11b0}, {pos = -145172608, events = 65535, fd = -1861234604, user_data = 0x0}, {pos = 1382377472, events = 1815956159, fd = -145172608,
user_data = 0xb82a910faedc <postmaster_child_launch+72>}, {pos = -145172544, events = 65535, fd = -1861210828, user_data = 0x0}, {pos = 0, events = 0, fd = 0,
user_data = 0x200000442}, {pos = -145172304, events = 65535, fd = -1861227892, user_data = 0xffff00000000}}
nevents = 1
__func__ = "ServerLoop"
#7 0x0000b82a910fea90 in PostmasterMain (argc=3, argv=0xb82a945195b0) at postmaster.c:1400
opt = -1
status = 0
userDoption = 0xb82a9455e4d0 "/pg/data"
listen_addr_saved = true
output_config_variable = 0x0
__func__ = "PostmasterMain"
#8 0x0000b82a90fb1970 in main (argc=3, argv=0xb82a945195b0) at main.c:227
do_check_root = true
dispatch_option = DISPATCH_POSTMASTER
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-09 21:06 Matheus Alcantara <[email protected]>
parent: Glauber Batista <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Matheus Alcantara @ 2026-06-09 21:06 UTC (permalink / raw)
To: Glauber Batista <[email protected]>; [email protected]
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)
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-09 21:44 Tomas Vondra <[email protected]>
parent: Matheus Alcantara <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Tomas Vondra @ 2026-06-09 21:44 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; Glauber Batista <[email protected]>; [email protected]
On 6/9/26 23:06, Matheus Alcantara wrote:
> 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];
>
So how does it get advanced past the prewarm_stop_idx? I've been unable
to reproduce it locally, maybe it's platform-specific. The original
report was from ARM, are you on ARM too, Matheus?
But AFAIK the code may not account for read stream callback updating the
pos to prewarm_stop_idx? The callback may end with (p->pos =
apw_state->prewarm_stop_idx), and that seems to be past the end of the
array.
That'd mean the proposed check is generally the correct way to fix this.
TBH it's not clear to me why this needs to set the *next* entry at the
end of the loop. Well, it does that so that the loop condition can use
'blk', but that seems a bit fragile / confusing, and no one noticed the
issue.
Maybe this would be a better way to write the while loop?
while (i < apw_state->prewarm_stop_idx)
{
blk = block_info[i];
if (blk.tablespace != tablespace ||
blk.filenumber != filenumber)
break;
...
}
regards
--
Tomas Vondra
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-09 22:25 Matheus Alcantara <[email protected]>
parent: Tomas Vondra <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Matheus Alcantara @ 2026-06-09 22:25 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; Glauber Batista <[email protected]>; [email protected]
On Tue Jun 9, 2026 at 6:44 PM -03, Tomas Vondra wrote:
> So how does it get advanced past the prewarm_stop_idx? I've been unable
> to reproduce it locally, maybe it's platform-specific. The original
> report was from ARM, are you on ARM too, Matheus?
>
Yes, I'm also on ARM. I also set pg_prewarm.autoprewarm_interval=10s on
postgresql.conf, not sure if it make more easier to reproduce.
> But AFAIK the code may not account for read stream callback updating the
> pos to prewarm_stop_idx? The callback may end with (p->pos =
> apw_state->prewarm_stop_idx), and that seems to be past the end of the
> array.
>
Yes, this is my understanding.
> That'd mean the proposed check is generally the correct way to fix this.
> TBH it's not clear to me why this needs to set the *next* entry at the
> end of the loop. Well, it does that so that the loop condition can use
> 'blk', but that seems a bit fragile / confusing, and no one noticed the
> issue.
>
> Maybe this would be a better way to write the while loop?
>
> while (i < apw_state->prewarm_stop_idx)
> {
> blk = block_info[i];
>
> if (blk.tablespace != tablespace ||
> blk.filenumber != filenumber)
> break;
>
> ...
> }
>
>
Is attached patch what are you sugesting? If yes, I agree that looks
better, it's more safe and easier to understand.
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
From ebf5296026b6f07fb30821ee0603fff24817001b Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 17:59:20 -0300
Subject: [PATCH v2] 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. When processing the last block, it
increments p->pos to prewarm_stop_idx before returning. The callback
itself is safe because it checks bounds before accessing the array.
However, the caller assigned blk from block_info[i] at the end of the
loop body, before the loop condition was re-evaluated. When i equaled
prewarm_stop_idx, this accessed memory beyond the allocated DSM segment,
causing a segfault.
Restructure the loop to check bounds at the top and assign blk at the
beginning of the loop body, where it is always safe. This avoids the
need for an explicit bounds check at the end.
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 | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index ba0bc8e6d4a..f3569b12d11 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -572,16 +572,23 @@ autoprewarm_database_main(Datum main_arg)
* valid forks or run out of options, we'll close the relation and
* move on.
*/
- while (i < apw_state->prewarm_stop_idx &&
- blk.tablespace == tablespace &&
- blk.filenumber == filenumber)
+ while (i < apw_state->prewarm_stop_idx)
{
- ForkNumber forknum = blk.forknum;
+ ForkNumber forknum;
BlockNumber nblocks;
struct AutoPrewarmReadStreamData p;
ReadStream *stream;
Buffer buf;
+ blk = block_info[i];
+
+ /* Stop when we reach a different relation. */
+ if (blk.tablespace != tablespace ||
+ blk.filenumber != filenumber)
+ break;
+
+ forknum = blk.forknum;
+
/*
* smgrexists is not safe for illegal forknum, hence check whether
* the passed forknum is valid before using it in smgrexists.
@@ -645,7 +652,6 @@ autoprewarm_database_main(Datum main_arg)
/* Advance i past all the blocks just prewarmed. */
i = p.pos;
- blk = block_info[i];
}
relation_close(rel, AccessShareLock);
--
2.50.1 (Apple Git-155)
Attachments:
[text/plain] v2-0001-Fix-out-of-bounds-access-in-autoprewarm-worker.patch (2.5K, ../../[email protected]/2-v2-0001-Fix-out-of-bounds-access-in-autoprewarm-worker.patch)
download | inline diff:
From ebf5296026b6f07fb30821ee0603fff24817001b Mon Sep 17 00:00:00 2001
From: Matheus Alcantara <[email protected]>
Date: Tue, 9 Jun 2026 17:59:20 -0300
Subject: [PATCH v2] 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. When processing the last block, it
increments p->pos to prewarm_stop_idx before returning. The callback
itself is safe because it checks bounds before accessing the array.
However, the caller assigned blk from block_info[i] at the end of the
loop body, before the loop condition was re-evaluated. When i equaled
prewarm_stop_idx, this accessed memory beyond the allocated DSM segment,
causing a segfault.
Restructure the loop to check bounds at the top and assign blk at the
beginning of the loop body, where it is always safe. This avoids the
need for an explicit bounds check at the end.
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 | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index ba0bc8e6d4a..f3569b12d11 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -572,16 +572,23 @@ autoprewarm_database_main(Datum main_arg)
* valid forks or run out of options, we'll close the relation and
* move on.
*/
- while (i < apw_state->prewarm_stop_idx &&
- blk.tablespace == tablespace &&
- blk.filenumber == filenumber)
+ while (i < apw_state->prewarm_stop_idx)
{
- ForkNumber forknum = blk.forknum;
+ ForkNumber forknum;
BlockNumber nblocks;
struct AutoPrewarmReadStreamData p;
ReadStream *stream;
Buffer buf;
+ blk = block_info[i];
+
+ /* Stop when we reach a different relation. */
+ if (blk.tablespace != tablespace ||
+ blk.filenumber != filenumber)
+ break;
+
+ forknum = blk.forknum;
+
/*
* smgrexists is not safe for illegal forknum, hence check whether
* the passed forknum is valid before using it in smgrexists.
@@ -645,7 +652,6 @@ autoprewarm_database_main(Datum main_arg)
/* Advance i past all the blocks just prewarmed. */
i = p.pos;
- blk = block_info[i];
}
relation_close(rel, AccessShareLock);
--
2.50.1 (Apple Git-155)
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-11 14:40 Tomas Vondra <[email protected]>
parent: Matheus Alcantara <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Tomas Vondra @ 2026-06-11 14:40 UTC (permalink / raw)
To: Matheus Alcantara <[email protected]>; Glauber Batista <[email protected]>; [email protected]; Melanie Plageman <[email protected]>
On 6/10/26 00:25, Matheus Alcantara wrote:
> On Tue Jun 9, 2026 at 6:44 PM -03, Tomas Vondra wrote:
>> So how does it get advanced past the prewarm_stop_idx? I've been unable
>> to reproduce it locally, maybe it's platform-specific. The original
>> report was from ARM, are you on ARM too, Matheus?
>>
>
> Yes, I'm also on ARM. I also set pg_prewarm.autoprewarm_interval=10s on
> postgresql.conf, not sure if it make more easier to reproduce.
>
>> But AFAIK the code may not account for read stream callback updating the
>> pos to prewarm_stop_idx? The callback may end with (p->pos =
>> apw_state->prewarm_stop_idx), and that seems to be past the end of the
>> array.
>>
>
> Yes, this is my understanding.
>
>> That'd mean the proposed check is generally the correct way to fix this.
>> TBH it's not clear to me why this needs to set the *next* entry at the
>> end of the loop. Well, it does that so that the loop condition can use
>> 'blk', but that seems a bit fragile / confusing, and no one noticed the
>> issue.
>>
>> Maybe this would be a better way to write the while loop?
>>
>> while (i < apw_state->prewarm_stop_idx)
>> {
>> blk = block_info[i];
>>
>> if (blk.tablespace != tablespace ||
>> blk.filenumber != filenumber)
>> break;
>>
>> ...
>> }
>>
>>
>
> Is attached patch what are you sugesting? If yes, I agree that looks
> better, it's more safe and easier to understand.
>
Yeah, that's roughly what I had in mind.
After looking a bit closer, I think this bug was introduced by
commit 6acab8bdbcda735ef47b1bb0ba2284d6c465cd88
Author: Melanie Plageman <[email protected]>
Date: Fri Apr 4 15:25:27 2025 -0400
Refactor autoprewarm_database_main() in preparation for read stream
which happens to advance to the next block in a couple places
blk = block_info[++i];
before we know it the incremented "i" is a valid element. The following
commit (d9c7911e1a5f adding the read stream) ends up doing the same
thing, except the index is incremented in a callback.
Melanie, do you agree with the proposed fix?
regards
--
Tomas Vondra
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-15 14:35 Melanie Plageman <[email protected]>
parent: Tomas Vondra <[email protected]>
0 siblings, 1 reply; 10+ messages in thread
From: Melanie Plageman @ 2026-06-15 14:35 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Glauber Batista <[email protected]>; [email protected]
On Thu, Jun 11, 2026 at 10:40 AM Tomas Vondra <[email protected]> wrote:
>
> After looking a bit closer, I think this bug was introduced by
>
> commit 6acab8bdbcda735ef47b1bb0ba2284d6c465cd88
> Author: Melanie Plageman <[email protected]>
> Date: Fri Apr 4 15:25:27 2025 -0400
>
> Refactor autoprewarm_database_main() in preparation for read stream
>
> which happens to advance to the next block in a couple places
>
> blk = block_info[++i];
>
> before we know it the incremented "i" is a valid element. The following
> commit (d9c7911e1a5f adding the read stream) ends up doing the same
> thing, except the index is incremented in a callback.
>
> Melanie, do you agree with the proposed fix?
Thanks all for investigating this! I agree that the proposed fix is
correct (both v1 and v2). I am a bit torn between the two versions.
v1:
i = p.pos;
if (i >= apw_state->prewarm_stop_idx)
break;
blk = block_info[i];
preserves what I had intended in that it sets blk as close to where i
was advanced as possible. I had wanted this behavior because we have
the "fast-forwarding" that happens in a few places in that loop, and I
was afraid it would get quite confusing. The other thing I wanted was
the invariant that blk is always the i'th block when exiting the loop.
This was in case future code restructured the outer loop and added
other break conditions and then used blk.
However, I do hate duplicating the loop bounds checking in two places.
And future code that restructures the control flow of this function is
going to have to be extremely careful anyway. The combination of
multiple nested loops, "fast-forwarding" behavior, and skipping
forward X number of blocks with the read stream made the requirements
of this function's control flow quite complex.
v2:
while (i < apw_state->prewarm_stop_idx)
{
ForkNumber forknum;
BlockNumber nblocks;
struct AutoPrewarmReadStreamData p;
ReadStream *stream;
Buffer buf;
blk = block_info[i];
/* Stop when we reach a different relation. */
if (blk.tablespace != tablespace ||
blk.filenumber != filenumber)
break;
has the advantage that we set blk directly before using it instead of
at the end of the previous iteration, which people may find less
confusing.
So, overall, I am fine with either approach. Whatever other hackers
find more clear is the right approach. In my attempt to make it clear,
I obviously made it incorrect -- which is far worse :)
- Melanie
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-26 17:55 Tomas Vondra <[email protected]>
parent: Melanie Plageman <[email protected]>
0 siblings, 2 replies; 10+ messages in thread
From: Tomas Vondra @ 2026-06-26 17:55 UTC (permalink / raw)
To: Melanie Plageman <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Glauber Batista <[email protected]>; [email protected]
FWIW I've committed the v2 fix (I liked it more), and I've backpatched
it to 18.
regards
--
Tomas Vondra
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-26 18:07 Matheus Alcantara <[email protected]>
parent: Tomas Vondra <[email protected]>
1 sibling, 0 replies; 10+ messages in thread
From: Matheus Alcantara @ 2026-06-26 18:07 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; Melanie Plageman <[email protected]>; +Cc: Glauber Batista <[email protected]>; [email protected]
On 26/06/26 14:55, Tomas Vondra wrote:
> FWIW I've committed the v2 fix (I liked it more), and I've backpatched
> it to 18.
>
Thank you!
--
Matheus Alcantara
EDB: https://www.enterprisedb.com
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-06-29 15:12 Melanie Plageman <[email protected]>
parent: Tomas Vondra <[email protected]>
1 sibling, 1 reply; 10+ messages in thread
From: Melanie Plageman @ 2026-06-29 15:12 UTC (permalink / raw)
To: Tomas Vondra <[email protected]>; +Cc: Matheus Alcantara <[email protected]>; Glauber Batista <[email protected]>; [email protected]
On Fri, Jun 26, 2026 at 1:55 PM Tomas Vondra <[email protected]> wrote:
>
> FWIW I've committed the v2 fix (I liked it more), and I've backpatched
> it to 18.
Thank you so much for doing this. I had it on my list for next week,
but a few other things got ahead of it. I really, really appreciate
you taking on committing it!
- Melanie
^ permalink raw reply [nested|flat] 10+ messages in thread
* Re: Autoprewarm workers terminated due to a segmentation fault
@ 2026-07-01 19:16 Glauber Batista <[email protected]>
parent: Melanie Plageman <[email protected]>
0 siblings, 0 replies; 10+ messages in thread
From: Glauber Batista @ 2026-07-01 19:16 UTC (permalink / raw)
To: Melanie Plageman <[email protected]>; +Cc: Tomas Vondra <[email protected]>; Matheus Alcantara <[email protected]>; [email protected]
Hello,
I finally got the chance and time to test the patch. I'm using it on a
replica for now and it's working as expected.
2026-07-01 19:09:35 UTC::@:[169848]:LOG: database system is ready to
accept read-only connections
2026-07-01 19:09:35 UTC::@:[174803]:LOG: started streaming WAL from
primary at B7E/24000000 on timeline 1
2026-07-01 19:09:35 UTC::@:[174804]:LOG: autoprewarm successfully
prewarmed 0 of 131072 previously-loaded blocks
Thank you all for your hard work!
Best,
Glauber Cassiano Batista
Em seg., 29 de jun. de 2026 às 12:13, Melanie Plageman <
[email protected]> escreveu:
> On Fri, Jun 26, 2026 at 1:55 PM Tomas Vondra <[email protected]> wrote:
> >
> > FWIW I've committed the v2 fix (I liked it more), and I've backpatched
> > it to 18.
>
> Thank you so much for doing this. I had it on my list for next week,
> but a few other things got ahead of it. I really, really appreciate
> you taking on committing it!
>
> - Melanie
>
^ permalink raw reply [nested|flat] 10+ messages in thread
end of thread, other threads:[~2026-07-01 19:16 UTC | newest]
Thread overview: 10+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2026-06-09 18:37 Autoprewarm workers terminated due to a segmentation fault Glauber Batista <[email protected]>
2026-06-09 21:06 ` Matheus Alcantara <[email protected]>
2026-06-09 21:44 ` Tomas Vondra <[email protected]>
2026-06-09 22:25 ` Matheus Alcantara <[email protected]>
2026-06-11 14:40 ` Tomas Vondra <[email protected]>
2026-06-15 14:35 ` Melanie Plageman <[email protected]>
2026-06-26 17:55 ` Tomas Vondra <[email protected]>
2026-06-26 18:07 ` Matheus Alcantara <[email protected]>
2026-06-29 15:12 ` Melanie Plageman <[email protected]>
2026-07-01 19:16 ` Glauber Batista <[email protected]>
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox