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 1x3rmw-006ilw-0j for pgsql-hackers@arkaria.postgresql.org; Tue, 08 Sep 2026 09:06:46 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1x3rmt-005vAW-33 for pgsql-hackers@arkaria.postgresql.org; Tue, 08 Sep 2026 09:06:43 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1x3rmt-005vAO-25 for pgsql-hackers@lists.postgresql.org; Tue, 08 Sep 2026 09:06:43 +0000 Received: from email.dnscdc.tech ([194.226.250.15]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1x3rmq-00000003YCc-3EhR for pgsql-hackers@lists.postgresql.org; Tue, 08 Sep 2026 09:06:43 +0000 Received: with id 22218280E8F; Tue, 8 Sep 2026 16:06:38 +0700 (+07) Received: with id B1BD2280037; Tue, 8 Sep 2026 16:06:37 +0700 (+07) From: Grigorev Jurij To: PostgreSQL Hackers CC: "michael@paquier.xyz" Subject: DSA_ALLOC_NO_OOM vs dsm_create ERROR leaving a half-initialized pgstats hash entry Thread-Topic: DSA_ALLOC_NO_OOM vs dsm_create ERROR leaving a half-initialized pgstats hash entry Thread-Index: AQHdP268ccO9PMgx5Ei0J2uuaTqIjA== Date: Tue, 8 Sep 2026 09:06:36 +0000 Message-ID: Accept-Language: ru-RU, en-US Content-Language: ru-RU X-MS-Has-Attach: X-MS-TNEF-Correlator: Content-Type: text/plain; charset="windows-1251" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-KLMS-Rule-ID: 1 X-KLMS-Message-Action: clean X-KLMS-AntiSpam-Lua-Profiles: 205795 [Sep 08 2026] X-KLMS-AntiSpam-Version: 6.1.1.27 X-KLMS-AntiSpam-Envelope-From: ju.grigorev@ftdata.ru X-KLMS-AntiSpam-Rate: 0 X-KLMS-AntiSpam-Status: not_detected X-KLMS-AntiSpam-Method: none X-KLMS-AntiSpam-Auth: dkim=none X-MS-Exchange-Organization-SCL: -1 X-KLMS-AntiSpam-Interceptor-Info: scan successful X-KLMS-AntiPhishing: Clean, bases: 2026/09/08 07:56:00 X-KLMS-AntiVirus: Kaspersky Security for Linux Mail Server, version 8.0.3.30, bases: 2026/09/08 08:05:00 #28554010 X-KLMS-AntiVirus-Status: Clean, skipped List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk Hi, I'm splitting this out of the pgstat_read_statsfile() cleanup thread [1], so that discussion can stay about the restore path. The case I reproduced is exactly that hole: dsa_allocate_extended(..., DSA_ALLOC_NO_OOM) can still raise ERROR from dsm_create() in make_new_segment(), after pgstat_init_entry() has marked the hash entry live and before its body is assigned. The NULL cleanup in pgstat_get_entry_ref() is then bypassed. I reproduced this on a running TAP cluster under ASan with a constrained /dev/shm (recovery/020_archive_status and 034_create_database). The same postgresql.log shows, about a second apart: FATAL: could not resize shared memory segment "/PostgreSQL.=85" to 1048576 bytes: No space left on device =85 then a later backend =85 AddressSanitizer: SEGV on unknown address 0x0 in pgstat_acquire_entry_ref() from pgstat_get_entry_ref() existing-entry path gdb on the crashing backend showed a live shared hash entry: dropped =3D false, refcount =3D 1, generation =3D 0, body =3D InvalidDsaPointer, kind =3D relation, dboid =3D 0, objid =3D pg_authid or pg_database There was no "Failed while allocating entry" / "could not allocate entry" message, so the InvalidDsaPointer cleanup added by 8191e0c did not run. On InitPostgres the ERROR is promoted to FATAL and the connecting backend exits, but the postmaster does not reinitialize shared memory, so the half-initialized entry remains visible. I see two possible layers at which to address this. 1. pgstats only: allocate the DSA body before inserting the shared hash entry, and initialize the entry only after a valid chunk has been obtained. A dsm_create() failure would then not leave a live entry whose body is InvalidDsaPointer. This is the "flip the order" approach discussed in [2]. It would require changing the two callers of pgstat_init_entry(), and dealing with a concurrently inserted entry by freeing the preallocated, unused chunk. 2. DSA/DSM: make DSA_ALLOC_NO_OOM cover failures to create or resize a new DSM segment as well, so dsa_allocate_extended() consistently returns InvalidDsaPointer for allocation failures instead of raising ERROR. This seems closer to the documented DSA_ALLOC_NO_OOM contract, but it is the lower-level change Michael mentioned. It would need to distingui= sh resource exhaustion, such as ENOSPC while resizing a POSIX shared memory object, from DSM failures that should still be reported as errors. I would rather not go back to PG_TRY/PG_CATCH around pgstat_init_entry(); that was considered in [2] and dropped in favour of returning NULL. Option (1) could close the pgstats corruption independently of the lower-level question. Option (2) would make the NO_OOM behavior consistent for other callers as well. I can prepare the pgstats patch for (1), or investigate the DSA/DSM approach first if you think that is the better layer. I can also add a deterministic failure-injection test for the new-segment path. Thanks, Yuriy Grigoryev [1] https://postgr.es/m/d55ecaf911844d53bd0a931751dce582@localhost.localdom= ain [2] https://postgr.es/m/CAAi9E7jELo5_-sBENftnc2E8XhW2PKZJWfTC3i2y-GMQd2bcqQ= @mail.gmail.com=