BUG #17607: Server process crashes when PLpgSQL function raises error in subtransaction

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: thomas(dot)d(dot)mckay(at)gmail(dot)com
Subject: BUG #17607: Server process crashes when PLpgSQL function raises error in subtransaction
Date: 2022-09-05 11:09:27
Message-ID: 17607-bd8ccc81226f7f80@postgresql.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

The following bug has been logged on the website:

Bug reference: 17607
Logged by: Thomas Mc Kay
Email address: thomas(dot)d(dot)mckay(at)gmail(dot)com
PostgreSQL version: 13.8
Operating system: Debian in docker
Description:

Hello,

I've encountered a bug while doing some SQL migrations on a PostgreSQL 13.8
server. My initial use-case is a Django app running migrations, a test setup
and a test, but that code was more than 10K lines of DDL, so I've reduced
the code to a minimal reproducible example (as best I could).

I also tested the same script in 14.0 and 14.5 and in both, the bug is
fixed. I haven't seen anything related to it in the changelog for 14.0, so I
don't know whether the bug was fixed purposefully and forgotten in the
changelog or if it was fixed by accident, maybe as a corollary of another
bugfix/feature. I also don't know if this is something the devs would want
to fix in the 13.x line. Either way, I figured it might make a good
regression test case for 14.x.

Environment (Docker):
- PostgreSQL 13.8 (Debian 13.8-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled
by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit

Test code:

```
-- Migration 1
CREATE TABLE "tbl" ("id" serial NOT NULL PRIMARY KEY);

-- Migration 2
ALTER TABLE "tbl" ADD COLUMN "value" int DEFAULT 0 NOT NULL;

CREATE FUNCTION on_tbl_parent_id_change_fn() RETURNS TRIGGER AS
$on_tbl_parent_id_change$
BEGIN
RAISE EXCEPTION 'BOOM !';
END
$on_tbl_parent_id_change$ LANGUAGE PLpgSQL VOLATILE;

CREATE TRIGGER on_tbl_parent_id_update
AFTER UPDATE ON tbl
REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows
FOR EACH STATEMENT
EXECUTE PROCEDURE on_tbl_parent_id_change_fn();

-- Test setup
INSERT INTO "tbl" ("value") VALUES (2);

-- Test
BEGIN;
SAVEPOINT svp;
UPDATE tbl SET value=1; -- Fails here
ROLLBACK TO SAVEPOINT svp;
ROLLBACK;
```

Output (verbose):

```
-- CREATE TABLE
-- ALTER TABLE
-- CREATE FUNCTION
-- CREATE TRIGGER
-- INSERT 0 1
-- BEGIN
-- SAVEPOINT
-- WARNING: 01000: AbortSubTransaction while in ABORT state
-- LOCATION: AbortSubTransaction, xact.c:4999
-- WARNING: 01000: AbortSubTransaction while in ABORT state
-- LOCATION: AbortSubTransaction, xact.c:4999
-- WARNING: 01000: AbortSubTransaction while in ABORT state
-- LOCATION: AbortSubTransaction, xact.c:4999
-- ERROR: P0001: BOOM !
-- CONTEXT: PL/pgSQL function on_tbl_parent_id_change_fn() line 3 at
RAISE
-- LOCATION: exec_stmt_raise, pl_exec.c:3854
-- ERROR: XX000: tupdesc reference 0x7fc02873fbc8 is not owned by resource
owner SubTransaction
-- LOCATION: ResourceOwnerForgetTupleDesc, resowner.c:1188
-- ERROR: XX000: tupdesc reference 0x7fc02873fbc8 is not owned by resource
owner SubTransaction
-- LOCATION: ResourceOwnerForgetTupleDesc, resowner.c:1188
-- ERROR: XX000: tupdesc reference 0x7fc02873fbc8 is not owned by resource
owner SubTransaction
-- LOCATION: ResourceOwnerForgetTupleDesc, resowner.c:1188
-- ERROR: XX000: tupdesc reference 0x7fc02873fbc8 is not owned by resource
owner SubTransaction
-- LOCATION: ResourceOwnerForgetTupleDesc, resowner.c:1188
-- PANIC: XX000: ERRORDATA_STACK_SIZE exceeded
-- LOCATION: errstart, elog.c:359
-- server closed the connection unexpectedly
-- This probably means the server terminated abnormally
-- before or while processing the request.
-- The connection to the server was lost. Attempting reset: Failed.
-- You are currently not connected to a database.
-- You are currently not connected to a database.
```

Expected output:
```
CREATE TABLE
ALTER TABLE
CREATE FUNCTION
CREATE TRIGGER
INSERT 0 1
BEGIN
SAVEPOINT
ERROR: BOOM !
CONTEXT: PL/pgSQL function on_tbl_parent_id_change_fn() line 3 at RAISE
ROLLBACK
ROLLBACK
```

The bug disappears if any of the following is true:
- value is added to the table definition and not with ALTER TABLE.
- value is declared without a default.
- `REFERENCING OLD TABLE AS old_rows NEW TABLE AS new_rows` is removed from
the trigger.
- a `VACUUM FULL tbl` is done between the trigger creation and the insert.

I don't know what to make of it, though.

Cheers,

Thomas

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message David Rowley 2022-09-05 12:13:13 Re: Startup process on a hot standby crashes with an error "invalid memory alloc request size 1073741824" while replaying "Standby/LOCK" records
Previous Message Dmitriy Kuzmin 2022-09-05 10:19:58 Startup process on a hot standby crashes with an error "invalid memory alloc request size 1073741824" while replaying "Standby/LOCK" records