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 1w2vrJ-000k0t-2Q for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Mar 2026 18:43:09 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1w2vrI-00DQP7-1m for pgsql-hackers@arkaria.postgresql.org; Wed, 18 Mar 2026 18:43:08 +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 1w2vrI-00DQOz-0V for pgsql-hackers@lists.postgresql.org; Wed, 18 Mar 2026 18:43:08 +0000 Received: from mail-ej1-x634.google.com ([2a00:1450:4864:20::634]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1w2vrE-00000000PJJ-3Ogs for pgsql-hackers@lists.postgresql.org; Wed, 18 Mar 2026 18:43:07 +0000 Received: by mail-ej1-x634.google.com with SMTP id a640c23a62f3a-b979d16dd0cso15761166b.1 for ; Wed, 18 Mar 2026 11:43:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1773859385; cv=none; d=google.com; s=arc-20240605; b=V/P8+I1ryQ7siXmP04OThIrc6gOLJ3grfLgVzK7OyfzYeSkqQpAJ6bafibWC3/u7XY soQPTsI3F64Qm/+3cQr00iZMKkJa/6mFxuNpVRCe2sJ6qy9PqEkNwkotBwLYf5R73Z7t BSFoe0ZVlTZQA4vUierhPAdSH2sQRd7lPvM7BkxCcrELgITGFHLx019QxE5YYW3Ij5Ij ieEKl2j+R4K5jhF91CBe5NHGI82kqGh4Jo50dNwtTluK/UAIFXVnzFgzxi1Je1DVJFOr UwRHSbpwygu5UbGaHNzdLBUWVmtEHbs3DVRcICDql78GPm8i1C6gWJQDDQyR21GIw2sX Yh/A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20240605; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=uuSJcrUe5LrzG96vr8iz0lRG8frwyxxgRigph/ZUyl8=; fh=8tLb1Z9j6fRL01y39n0tBIsPIe3f8Jkd1ltuOUq52JA=; b=YxdLiSh79jYIx+WVqWo0HgWE7C1EqwAhmRjnP/PNtirSS5lM4On4N1zrvxtvRqXdrJ n2ADp6rzAcgruopwU/rkxodxU9a7x2/xwBBUHPEU0Pxfrod6DeGVJpKjkXjvYxfOkzKl 2MkMLLgVXGr6r0VSWjfjN4O1pqHy4XYlzGno3eRf0ul3GVX+DWOhGiOzXTJJe3dGMwEV KqwDAK/RRyvzMmop4qVON76cN7qPfQSD4+w3Cuwc8DGjVNvCFZmj8U7aSPiSCiqPrwCr 79UMnPT5dIpPgyq7ceJqNVhOKYOXwS7VdIwRXRtBKtvMzTL4B8fgFV6MVzuuZILQEhBl 0ClQ==; darn=lists.postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1773859385; x=1774464185; darn=lists.postgresql.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=uuSJcrUe5LrzG96vr8iz0lRG8frwyxxgRigph/ZUyl8=; b=mU486S2WJiMmIxqudQs1Ajmvis31+d2xvR2izW+NX4KEfkdeR4iy9wieKihP2alVoU 76M66xkL8gMtv27r2E1DCTmGlITus0k0GsF8w1IuVaMBoJyFz0c4y24zEbfNMUBvHEm9 EUe3CIA+OIHkzt0bjv9Tdjx7OqKDKovQ1bVzUw50USPYAq5zmGfI6Dk5gI4OqcgmQpeJ XsyIsjnDaDv2BXVb26ARENVHi2Vdm+0XYbuebTtOLNtOjc7T6LiceL+fwqUcQ706aGXm EjlxU3k7EQ/qCTuLHCqfxuYgi8ud0P1qvCQeCNdaaQQ5tfXTvHJGJ7PLOq9wo5g0o4xl LGqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1773859385; x=1774464185; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=uuSJcrUe5LrzG96vr8iz0lRG8frwyxxgRigph/ZUyl8=; b=ODZHTZUM7WkdMKO6IxgddPliSFcACo2aRDhK4dDACUj6Oiqc/OQh0XtdYxSpzYqBue JqbZyJ0UCKTw0quRV/5/iSRzSjfqKskIxas2D6AaHGaawYxWkzo9PD+WOuwj287HFtJS sD1rmxXA6bHSr8KD04h8N3N7oO+J60rIzYYjCxtjbfM2xoedYer4Q2QcGzCP8NYkdyRU Ja/VU1hVr4EalbcvKTArBkB1Npz/yPLLmj+9cRygszL4bReIA4Ce5bFX2fvap3xuxyoz npNHLFb07R+XwU98IcYF7pBYGG/OZW2i8Hvzjx5Bm0aWvtzhit4+ks3M+AxhI8QGlQhE b0gA== X-Gm-Message-State: AOJu0Yycnk/eghnjz3Wn1YD55i3ZkfsW/Zd+HfUMD90nRXhx0f/lb/Lk ri1l8gjrykbS5WTKuj/JXpx71f+l6xNxovddaEfxSnaaE8stBTGdVJ711su/wZIWEsp5jjuC1ZF k9+9bI0Mktf8DB2G3NshZfs24a6wdtqg= X-Gm-Gg: ATEYQzwVY2EFBiLeSpjDvuRzz3Aj2CCG+pzmURMQTF6qfysFnPDReEbS2NdUXSXIBDi PfSyD3jcREm5Ft8jMsxgR3nivVZR95Du8WRHHQwTRYXdk3S1GTaZ1M+sUGkGN/tYTTA72sk+2kG UTFH7PKL89oOxc5+JTesem44r+HnNz8HWVD8MrzR7HrO2p6gsQUVmn2gFkk3WyMlWbGduCQNOcH Qo+7jBqHKlcGnz8HL3A5DWcvuVmkNALq2pxZKuOkitAocHp7+gJbk9PdU7yG5oBcTKH4SyulNC7 c0GTDSSatlOFI0FdyQMIYRxbnTweLgwWqBvK4UQ= X-Received: by 2002:a17:907:3f85:b0:b97:76dc:ebb with SMTP id a640c23a62f3a-b97f4aaad7cmr271032666b.40.1773859384527; Wed, 18 Mar 2026 11:43:04 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Robert Haas Date: Wed, 18 Mar 2026 14:42:52 -0400 X-Gm-Features: AaiRm536ASkKCYPY3mJUjFJ9V7fRrcCBQBvtx5CRYWpGAQro6sFnrkD62HzWzXo Message-ID: Subject: Re: dshash_find_or_insert vs. OOM To: Sami Imseih Cc: PostgreSQL Hackers , Andres Freund , Thomas Munro Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Wed, Mar 18, 2026 at 11:21=E2=80=AFAM Sami Imseih = wrote: > Passing this as a flag seems OK with me. Not sure what other > flags could be added in the future, but the flexibility is a good > thing, IMO. I was debating if this should just be a dsh_params > option, but maybe for the same dshash a caller may want OOM > in some code path, and retry in some other. maybe? Yeah, I think this is a property of the individual call to dshash_find_or_insert(), rather than a property of the table. It does seem likely that most callers will want the same behavior in all cases, but it would be very sad if we embedded that idea into the structure of the code and then somebody has a case where it's not what they want, and I see no real reason why that couldn't happen. Also, doing it that way wouldn't really follow existing precedents (pg_malloc_extended, palloc_extended, MemoryContextAllocExtended, dsa_allocate_extended). > I did some testing by triggering an OOM, a no-OOM, and an OOM with > eviction afterwards, as a sanity check. All looks good. > I've attached the tests I created with other basic testing, as dshash > lacks direct testing in general, if you're inclined to add them. I tried running a coverage report for this. It's pretty good. It doesn't cover these things: - dshash_create: OOM while allocating the bucket array. - dshash_find_or_insert_extended: OOM while inserting an item (apparently, at least here, it instead hits OOM while resizing) - dshash_delete_key: the case where the entry not found - dshash_dump: not called at all - resize: the case where we exit early due to a concurrent resize - delete_item_from_bucket: the case where there is more than one item in the bucket I think that adding a call to dshash_dump() somewhere would probably make sense, and I'd suggest also trying to delete a nonexistent key. The rest don't seem worth worrying about. On the code itself: + /* Verify all entries via find. */ + for (int i =3D 0; i < count; i++) + { + entry =3D dshash_find(ht, &i, false); + if (entry =3D=3D NULL) + elog(ERROR, "key %d not found", i); + dshash_release_lock(ht, entry); + } You could verify that entry->key =3D=3D i. The current code wouldn't notice if the hash table returned a garbage pointer. You could possibly also include some kind of a payload in each record and verify that, e.g. set entry->value =3D some_homomorphism_over_0_to_9(entry->key). + dsa_set_size_limit(area, dsa_minimum_size()); This is an abuse of the documented purpose of dsa_set_size_limit(). Seems better to just pick a constant here. + /* Insert until OOM =E2=80=94 without NO_OOM flag, this should raise E= RROR. */ + for (;;) I think it would be safer to code this as a fixed iteration count. For example, if you choose the size limit so that we should run out of memory after 10 entries, you could terminate this loop after 1000 iterations. That way, if something goes wrong, we're more likely to see "expected out-of-memory, but completed all %d iterations" in the log rather than a core dump or whatever. I+ { + TestDshashEntry *entry; + + entry =3D dshash_find_or_insert(ht, &key, &found); + dshash_release_lock(ht, entry); + key++; + } In other places, you check for entry =3D=3D NULL, but not here. + { + TestDshashEntry *entry; + + entry =3D dshash_find_or_insert_extended(ht, &key, &found, + DSHASH_INSERT_NO_OOM); + if (entry =3D=3D NULL) + elog(ERROR, "insert after eviction failed"); + dshash_release_lock(ht, entry); + } I just got in trouble for letting a bare block sneak into my code, so now it's my turn to complain. I suggest git config user.email in whatever directory you use to generate patches like this, just to make life a bit easier for anyone who might eventually be committing one of them. --=20 Robert Haas EDB: http://www.enterprisedb.com