commit 019c04add75050e4c98e406ccbc1682ab2e7243e
parent 53a94687260c75ab3febf17f6f76c25bb7ff1eb3
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 5 Aug 2026 23:26:04 +0200
lock row for update to ensure we do not trip the assert on concurrent DELETE
Diffstat:
2 files changed, 25 insertions(+), 1 deletion(-)
diff --git a/src/backenddb/test_merchantdb.c b/src/backenddb/test_merchantdb.c
@@ -2070,6 +2070,28 @@ run_test_products (struct TestProducts_Closure *cls)
TEST_RET_ON_FAIL (test_lookup_products (&cls->instance,
0,
NULL));
+ /* Updating a product that has just been deleted must be reported via
+ 'no_product' (which the HTTP layer turns into a 404), never as a
+ hard error. merchant_do_update_product re-reads the inventory row
+ and then ASSERTs that the subsequent UPDATE still finds it; without
+ the FOR UPDATE on that re-read, a DELETE committing in the window
+ between the two statements turns this into a P0004 assertion
+ failure (HTTP 500). Reproducing that window needs a second
+ database connection, which this harness does not have; what is
+ asserted here is that the very same code path returns 'no_product'
+ when the row is gone. */
+ TEST_RET_ON_FAIL (test_update_product (
+ &cls->instance,
+ &cls->products[0],
+ 0,
+ NULL,
+ GNUNET_DB_STATUS_SUCCESS_ONE_RESULT,
+ false,
+ true,
+ false,
+ false,
+ false,
+ -1));
return 0;
}
diff --git a/src/backenddb/update_product.sql b/src/backenddb/update_product.sql
@@ -91,7 +91,9 @@ SELECT total_stock
,product_serial
INTO rec
FROM merchant_inventory
- WHERE product_id=in_product_id;
+ WHERE product_id=in_product_id
+ FOR UPDATE; -- lock, or a concurrent DELETE makes the UPDATE below
+ -- fail the ASSERT (=> HTTP 500 instead of 404)
IF NOT FOUND
THEN