BUG #17607: Server process crashes when PLpgSQL function raises error in subtransaction - Mailing list pgsql-bugs

From PG Bug reporting form
Subject BUG #17607: Server process crashes when PLpgSQL function raises error in subtransaction
Date
Msg-id 17607-bd8ccc81226f7f80@postgresql.org
Whole thread Raw
Responses Re: BUG #17607: Server process crashes when PLpgSQL function raises error in subtransaction
List pgsql-bugs
The following bug has been logged on the website:

Bug reference:      17607
Logged by:          Thomas Mc Kay
Email address:      thomas.d.mckay@gmail.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


pgsql-bugs by date:

Previous
From: Dmitriy Kuzmin
Date:
Subject: Startup process on a hot standby crashes with an error "invalid memory alloc request size 1073741824" while replaying "Standby/LOCK" records
Next
From: David Rowley
Date:
Subject: Re: Startup process on a hot standby crashes with an error "invalid memory alloc request size 1073741824" while replaying "Standby/LOCK" records