BUG #16630: TupleDesc reference leak: TupleDesc 0x7fad89c9c928 (16386,-1) still referenced

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: pg(at)pmenke(dot)de
Subject: BUG #16630: TupleDesc reference leak: TupleDesc 0x7fad89c9c928 (16386,-1) still referenced
Date: 2020-09-23 08:26:55
Message-ID: 16630-421ade67bea6f5e1@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: 16630
Logged by: Philipp Menke
Email address: pg(at)pmenke(dot)de
PostgreSQL version: 13rc1
Operating system: Linux
Description:

Hi there,

i was playing around with transaction control statements to make changes of
a long-running processing procedure visible and stumbled over the following
warning / error:

```
WARNING: TupleDesc reference leak: TupleDesc 0x7f4207cbcf20 (16386,-1)
still referenced
WARNING: TupleDesc reference leak: TupleDesc 0x7f4207cbcf20 (16386,-1)
still referenced
ERROR: tupdesc reference 0x7f4207cbcf20 is not owned by resource owner
TopTransaction
```

As i don't think this is expected behavior when executing some "plain"
pl/pgsql, i figured i should report it.
I boiled the causing code down to the following example, which reproduces
the error:

```
CREATE TABLE test_output(tuple INT);
DECLARE test_cursor CURSOR WITH HOLD FOR SELECT * FROM generate_series(1,
1000);
DO LANGUAGE plpgsql $$
DECLARE
v_counter INT;
v_tuple test_output;
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_data (tuple INT);
WHILE TRUE LOOP
v_counter := 0;
TRUNCATE tmp_data;
EXECUTE 'FETCH FROM test_cursor' INTO v_tuple;
WHILE v_tuple IS NOT NULL AND v_counter < 100 LOOP
IF v_tuple IS NOT NULL THEN
INSERT INTO tmp_data VALUES (v_tuple.*);
v_counter := v_counter + 1;
END IF;
IF v_counter < 100 THEN
EXECUTE 'FETCH FROM test_cursor' INTO v_tuple;
END IF;
END LOOP;
IF v_counter > 0 THEN
-- in my normal program i would have processed tmp_data here
COMMIT;
ELSE
RETURN;
END IF;
END LOOP;
END;
$$;
```

I've tested this with PostgreSQL 12.4 as well as with 13-rc1 through the
following procedure:

In one terminal run: `docker run -e POSTGRES_HOST_AUTH_METHOD=trust
postgres:13-rc1`
In another terminal run: `docker exec -ttiu postgres $(docker ps -q)
/usr/bin/psql`
In this second terminal execute the example code:
```
psql (13rc1 (Debian 13~rc1-1.pgdg100+1))
Type "help" for help.

postgres=# CREATE TABLE test_output(tuple INT);
CREATE TABLE
postgres=# DECLARE test_cursor CURSOR WITH HOLD FOR SELECT * FROM
generate_series(1, 1000);
DECLARE CURSOR
postgres=# DO LANGUAGE plpgsql $$
postgres$# DECLARE
postgres$# v_counter INT;
postgres$# v_tuple test_output;
postgres$# BEGIN
postgres$# CREATE TEMPORARY TABLE IF NOT EXISTS tmp_data (tuple INT);
postgres$# WHILE TRUE LOOP
postgres$# v_counter := 0;
postgres$# TRUNCATE tmp_data;
postgres$# EXECUTE 'FETCH FROM test_cursor' INTO v_tuple;
postgres$# WHILE v_tuple IS NOT NULL AND v_counter < 100 LOOP
postgres$# IF v_tuple IS NOT NULL THEN
postgres$# INSERT INTO tmp_data VALUES (v_tuple.*);
postgres$# v_counter := v_counter + 1;
postgres$# END IF;
postgres$# IF v_counter < 100 THEN
postgres$# EXECUTE 'FETCH FROM test_cursor' INTO v_tuple;
postgres$# END IF;
postgres$# END LOOP;
postgres$# IF v_counter > 0 THEN
postgres$# -- in my normal program i would have processed
tmp_data here
postgres$# COMMIT;
postgres$# ELSE
postgres$# RETURN;
postgres$# END IF;
postgres$# END LOOP;
postgres$# END;
postgres$# $$;
WARNING: TupleDesc reference leak: TupleDesc 0x7f0b2a60af20 (16386,-1)
still referenced
WARNING: TupleDesc reference leak: TupleDesc 0x7f0b2a60af20 (16386,-1)
still referenced
ERROR: tupdesc reference 0x7f0b2a60af20 is not owned by resource owner
TopTransaction
```

The server log (in the first terminal) will yield:
```
2020-09-23 08:11:06.619 UTC [1] LOG: database system is ready to accept
connections
2020-09-23 08:11:16.135 UTC [75] WARNING: TupleDesc reference leak:
TupleDesc 0x7f0b2a60af20 (16386,-1) still referenced
2020-09-23 08:11:16.135 UTC [75] CONTEXT: PL/pgSQL function
inline_code_block line 22 at COMMIT
2020-09-23 08:11:16.136 UTC [75] WARNING: TupleDesc reference leak:
TupleDesc 0x7f0b2a60af20 (16386,-1) still referenced
2020-09-23 08:11:16.136 UTC [75] CONTEXT: PL/pgSQL function
inline_code_block line 22 at COMMIT
2020-09-23 08:11:16.178 UTC [75] ERROR: tupdesc reference 0x7f0b2a60af20 is
not owned by resource owner TopTransaction
2020-09-23 08:11:16.178 UTC [75] STATEMENT: DO LANGUAGE plpgsql $$
DECLARE
v_counter INT;
v_tuple test_output;
BEGIN
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_data (tuple INT);
WHILE TRUE LOOP
v_counter := 0;
TRUNCATE tmp_data;
EXECUTE 'FETCH FROM test_cursor' INTO v_tuple;
WHILE v_tuple IS NOT NULL AND v_counter < 100 LOOP
IF v_tuple IS NOT NULL THEN
INSERT INTO tmp_data VALUES (v_tuple.*);
v_counter := v_counter + 1;
END IF;
IF v_counter < 100 THEN
EXECUTE 'FETCH FROM test_cursor' INTO v_tuple;
END IF;
END LOOP;
IF v_counter > 0 THEN
-- in my normal program i would have processed tmp_data
here
COMMIT;
ELSE
RETURN;
END IF;
END LOOP;
END;
$$;
```

As i was just fooling around with the feature, this bug is not critical to
me personally. But i might deserve a look.

Thank you for your otherwise awesome product and kind regards,
Philipp

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Brian Kanaga 2020-09-23 13:47:31 RE: BUG #16627: union all with partioned table yields random aggregate results
Previous Message David Rowley 2020-09-23 03:10:08 Re: BUG #16627: union all with partioned table yields random aggregate results