Re: PL/Python: Fix return in the middle of PG_TRY() block.

From: Andres Freund <andres(at)anarazel(dot)de>
To: Nathan Bossart <nathandbossart(at)gmail(dot)com>
Cc: Xing Guo <higuoxing(at)gmail(dot)com>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: PL/Python: Fix return in the middle of PG_TRY() block.
Date: 2023-01-13 05:49:00
Message-ID: 20230113054900.b7onkvwtkrykeu3z@awork3.anarazel.de
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

On 2023-01-12 10:44:33 -0800, Nathan Bossart wrote:
> On Thu, Jan 12, 2023 at 11:19:29PM +0800, Xing Guo wrote:
> > @@ -690,12 +690,12 @@ PLy_trigger_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc, HeapTuple *r
> > PyObject *volatile pltdata = NULL;
> > char *stroid;
> >
> > + pltdata = PyDict_New();
> > + if (!pltdata)
> > + return NULL;
> > +
> > PG_TRY();
> > {
> > - pltdata = PyDict_New();
> > - if (!pltdata)
> > - return NULL;
> > -
> > pltname = PLyUnicode_FromString(tdata->tg_trigger->tgname);
> > PyDict_SetItemString(pltdata, "name", pltname);
> > Py_DECREF(pltname);
>
> There's another "return" later on in this PG_TRY block. I wonder if it's
> possible to detect this sort of thing at compile time.

Clang provides some annotations that allow to detect this kind of thing. I
hacked up a test for this, and it finds quite a bit of prolematic
code. plpython is, uh, not being good? But also in plperl, pltcl.

Example complaints:

[776/1239 42 62%] Compiling C object src/pl/plpython/plpython3.so.p/plpy_exec.c.o
../../../../home/andres/src/postgresql/src/pl/plpython/plpy_exec.c:472:1: warning: no_returns_in_pg_try 'no_returns_handle' is not held on every path through here [-Wthread-safety-analysis]
}
^
../../../../home/andres/src/postgresql/src/pl/plpython/plpy_exec.c:417:2: note: no_returns_in_pg_try acquired here
PG_TRY();
^
../../../../home/andres/src/postgresql/src/include/utils/elog.h:424:7: note: expanded from macro 'PG_TRY'
no_returns_start(no_returns_handle##__VA_ARGS__)
^
...
[785/1239 42 63%] Compiling C object src/pl/tcl/pltcl.so.p/pltcl.c.o
../../../../home/andres/src/postgresql/src/pl/tcl/pltcl.c:1830:1: warning: no_returns_in_pg_try 'no_returns_handle' is not held on every path through here [-Wthread-safety-analysis]
}
^
../../../../home/andres/src/postgresql/src/pl/tcl/pltcl.c:1809:2: note: no_returns_in_pg_try acquired here
PG_CATCH();
^
../../../../home/andres/src/postgresql/src/include/utils/elog.h:433:7: note: expanded from macro 'PG_CATCH'
no_returns_start(no_returns_handle##__VA_ARGS__)
^

Not perfect digestible, but also not too bad. I pushed the
no_returns_start()/no_returns_stop() calls into all the PG_TRY related macros,
because that causes the warning to point to block that the problem is
in. E.g. above the first warning points to PG_TRY, the second to
PG_CATCH. It'd work to just put it into PG_TRY and PG_END_TRY.

Clearly this would need a bunch more work, but it seems promising? I think
there'd be other uses than this.

I briefly tried to use it for spinlocks. Mostly works and detects things like
returning with a spinlock held. But it does not like dynahash's habit of
conditionally acquiring and releasing spinlocks.

Greetings,

Andres Freund

Attachment Content-Type Size
v1-0001-wip-use-clang-anotations-to-warn-if-code-in-PG_TR.patch text/x-diff 3.4 KB

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Andres Freund 2023-01-13 05:49:39 Re: Cygwin cleanup
Previous Message Masahiko Sawada 2023-01-13 05:43:21 Re: Perform streaming logical transactions by background workers and parallel apply