Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wX4FS-0032By-1H for pgsql-bugs@arkaria.postgresql.org; Tue, 09 Jun 2026 21:44:38 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wX4FR-008UYt-12 for pgsql-bugs@arkaria.postgresql.org; Tue, 09 Jun 2026 21:44:37 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1wX4FR-008UYi-03 for pgsql-bugs@lists.postgresql.org; Tue, 09 Jun 2026 21:44:37 +0000 Received: from relay2-d.mail.gandi.net ([217.70.183.194]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1wX4FO-00000001uZA-1DG2 for pgsql-bugs@lists.postgresql.org; Tue, 09 Jun 2026 21:44:36 +0000 Received: by mail.gandi.net (Postfix) with ESMTPSA id 0F1E33EBB1; Tue, 9 Jun 2026 21:44:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vondra.me; s=gm1; t=1781041469; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=yDGTbWYwxUvcVipe8OaWUbsU020VpNTeYvIl4M5LBzA=; b=YwipA0PPq13YFtxZ08hzsxj6aypHPMGQdGukpxBeB0uDLusXcZ1xJYR0v3bzJbNhAoCiQh yUDYfFLgt6C235pZEIkdm88cSgiiRZ+jeEtvszMnT+S3eHYRa3yW3m6xntYtkw39y7BbNR TTEfJYqALZl0ni7GeN9uaVifFxUvwTtBCYGGhAEVehl4T0aC5+3CP4WnRV6KtwjTGyZqA2 A6e7Qo06ThwsVIQXcW4gYoDY8w69EgrgdZWDN97C2LNZZiXKspcfs3IOwXyYxA5eng8QOk SexseLwz4PHMpFgBfq9DPfyhPrmG/1M4K4xIuAgm47hamqcvOmIDYXua6zWoxg== Message-ID: Date: Tue, 9 Jun 2026 23:44:28 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: Autoprewarm workers terminated due to a segmentation fault To: Matheus Alcantara , Glauber Batista , pgsql-bugs@lists.postgresql.org References: Content-Language: en-US From: Tomas Vondra In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-GND-Sasl: tomas@vondra.me X-GND-State: clean X-GND-Score: -100 X-GND-Cause: dmFkZTGKN1T0o9bOfddlz/0+88nJ/8vq5p4MvbQkKLtmlWs03uiAiYj/ar6cGuvVyi0ornTzMkv6Ex/7DDQsO1WRwdoIdvccDjq4VuWYawEraDPugiD7otHVOy6SIfsi94PV8nKpT91gwehnaXozkjpw2GO9lV3J57sWecf3JC3TBNOBW2Crr76UqfwC3pNN+DQwgYZHHgZFHqYnPgp4O2l+HnBrXo/kc0H/jFggiCzRs53ZMNpjIjdvVu+it3NvRBiVSfud6OMgc3tPLDTFd5UXD7UpjXEmEyQbVZ2IDpePFJpY2xO1Wv5NxMQt/9JOp4NFvGRtSJO4Fjp8wB5/snfVIGQQSSTEndd4JMBFNmKD5+DKTE65lYP/rc2WUEIwJPPOnwbn57dh/CfMFSz6aKn1gB6VW5eYVmRUDg9bBfhgjuFvcWzF/YzJ8+DOnVSH0OYGOT+6hRiVBMdMvzzMD0aBwUQQVWgH7dwzRxlHfRCVkqZdkwfIM8m6VyZWCCWwyxxJ7jAkI3qrNuibaf98oy1Ftik3lFBaApvhv25gatyFoIiX23UZ7jSpSn0UazZhrkpe0G9ND9kLgOYs279feVXB8FXZgZYWMeiltLIW6TYZNqtegSWzIAMKkVx9jB1ohSA4MIXsyg6VRRolv3Sb4RxjbbijdES8C+hUuRZmK9mtaT9J2g List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk 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