Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdb1c597

Browse files
committed
Fix broken logic for reporting PL/Python function names in errcontext.
plpython_error_callback() reported the name of the function associatedwith the topmost PL/Python execution context. This was not merelywrong if there were nested PL/Python contexts, but it risked a coredump if the topmost one is an inline code block rather than a namedfunction. That will have proname = NULL, and so we were passing a NULLpointer to snprintf("%s"). It seems that none of the PL/Python-testingmachines in the buildfarm will dump core for that, but some platforms do,as reported by Marina Polyakova.Investigation finds that there actually is an existing regression testthat used to prove that the behavior was wrong, though apparently no onehad noticed that it was printing the wrong function name. It stoppedshowing the problem in 9.6 when we adjusted psql to not print CONTEXTby default for NOTICE messages. The problem is masked (if your platformavoids the core dump) in error cases, because PL/Python will throw awaythe originally generated error info in favor of a new traceback producedat the outer level.Repair by using ErrorContextCallback.arg to pass the correct context tothe error callback. Add a regression test illustrating correct behavior.Back-patch to all supported branches, since they're all broken this way.Discussion:https://postgr.es/m/156b989dbc6fe7c4d3223cf51da61195@postgrespro.ru
1 parentdc9f8fb commitdb1c597

File tree

7 files changed

+113
-30
lines changed

7 files changed

+113
-30
lines changed

‎src/pl/plpython/expected/plpython_error.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,26 @@ EXCEPTION WHEN SQLSTATE 'SILLY' THEN
426426
-- NOOP
427427
END
428428
$$ LANGUAGE plpgsql;
429+
/* test the context stack trace for nested execution levels
430+
*/
431+
CREATE FUNCTION notice_innerfunc() RETURNS int AS $$
432+
plpy.execute("DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$")
433+
return 1
434+
$$ LANGUAGE plpythonu;
435+
CREATE FUNCTION notice_outerfunc() RETURNS int AS $$
436+
plpy.execute("SELECT notice_innerfunc()")
437+
return 1
438+
$$ LANGUAGE plpythonu;
439+
\set SHOW_CONTEXT always
440+
SELECT notice_outerfunc();
441+
NOTICE: inside DO
442+
CONTEXT: PL/Python anonymous code block
443+
SQL statement "DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$"
444+
PL/Python function "notice_innerfunc"
445+
SQL statement "SELECT notice_innerfunc()"
446+
PL/Python function "notice_outerfunc"
447+
notice_outerfunc
448+
------------------
449+
1
450+
(1 row)
451+

‎src/pl/plpython/expected/plpython_error_0.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,26 @@ EXCEPTION WHEN SQLSTATE 'SILLY' THEN
426426
-- NOOP
427427
END
428428
$$ LANGUAGE plpgsql;
429+
/* test the context stack trace for nested execution levels
430+
*/
431+
CREATE FUNCTION notice_innerfunc() RETURNS int AS $$
432+
plpy.execute("DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$")
433+
return 1
434+
$$ LANGUAGE plpythonu;
435+
CREATE FUNCTION notice_outerfunc() RETURNS int AS $$
436+
plpy.execute("SELECT notice_innerfunc()")
437+
return 1
438+
$$ LANGUAGE plpythonu;
439+
\set SHOW_CONTEXT always
440+
SELECT notice_outerfunc();
441+
NOTICE: inside DO
442+
CONTEXT: PL/Python anonymous code block
443+
SQL statement "DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$"
444+
PL/Python function "notice_innerfunc"
445+
SQL statement "SELECT notice_innerfunc()"
446+
PL/Python function "notice_outerfunc"
447+
notice_outerfunc
448+
------------------
449+
1
450+
(1 row)
451+

‎src/pl/plpython/expected/plpython_error_5.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,3 +426,26 @@ EXCEPTION WHEN SQLSTATE 'SILLY' THEN
426426
-- NOOP
427427
END
428428
$$ LANGUAGE plpgsql;
429+
/* test the context stack trace for nested execution levels
430+
*/
431+
CREATE FUNCTION notice_innerfunc() RETURNS int AS $$
432+
plpy.execute("DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$")
433+
return 1
434+
$$ LANGUAGE plpythonu;
435+
CREATE FUNCTION notice_outerfunc() RETURNS int AS $$
436+
plpy.execute("SELECT notice_innerfunc()")
437+
return 1
438+
$$ LANGUAGE plpythonu;
439+
\set SHOW_CONTEXT always
440+
SELECT notice_outerfunc();
441+
NOTICE: inside DO
442+
CONTEXT: PL/Python anonymous code block
443+
SQL statement "DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$"
444+
PL/Python function "notice_innerfunc"
445+
SQL statement "SELECT notice_innerfunc()"
446+
PL/Python function "notice_outerfunc"
447+
notice_outerfunc
448+
------------------
449+
1
450+
(1 row)
451+

‎src/pl/plpython/expected/plpython_subtransaction.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ SELECT subtransaction_deeply_nested_test();
182182
NOTICE: Swallowed SyntaxError('syntax error at or near "error"',)
183183
CONTEXT: PL/Python function "subtransaction_nested_test"
184184
SQL statement "SELECT subtransaction_nested_test('t')"
185-
PL/Python function "subtransaction_nested_test"
185+
PL/Python function "subtransaction_deeply_nested_test"
186186
subtransaction_deeply_nested_test
187187
-----------------------------------
188188
ok

‎src/pl/plpython/plpy_main.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -257,23 +257,26 @@ plpython_call_handler(PG_FUNCTION_ARGS)
257257
/*
258258
* Push execution context onto stack. It is important that this get
259259
* popped again, so avoid putting anything that could throw error between
260-
* here and the PG_TRY. (plpython_error_callback expects the stack entry
261-
* to be there, so we have to make the context first.)
260+
* here and the PG_TRY.
262261
*/
263262
exec_ctx=PLy_push_execution_context();
264263

265-
/*
266-
* Setup error traceback support for ereport()
267-
*/
268-
plerrcontext.callback=plpython_error_callback;
269-
plerrcontext.previous=error_context_stack;
270-
error_context_stack=&plerrcontext;
271-
272264
PG_TRY();
273265
{
274266
Oidfuncoid=fcinfo->flinfo->fn_oid;
275267
PLyProcedure*proc;
276268

269+
/*
270+
* Setup error traceback support for ereport(). Note that the PG_TRY
271+
* structure pops this for us again at exit, so we needn't do that
272+
* explicitly, nor do we risk the callback getting called after we've
273+
* destroyed the exec_ctx.
274+
*/
275+
plerrcontext.callback=plpython_error_callback;
276+
plerrcontext.arg=exec_ctx;
277+
plerrcontext.previous=error_context_stack;
278+
error_context_stack=&plerrcontext;
279+
277280
if (CALLED_AS_TRIGGER(fcinfo))
278281
{
279282
Relationtgrel= ((TriggerData*)fcinfo->context)->tg_relation;
@@ -299,9 +302,7 @@ plpython_call_handler(PG_FUNCTION_ARGS)
299302
}
300303
PG_END_TRY();
301304

302-
/* Pop the error context stack */
303-
error_context_stack=plerrcontext.previous;
304-
/* ... and then the execution context */
305+
/* Destroy the execution context */
305306
PLy_pop_execution_context();
306307

307308
returnretval;
@@ -345,21 +346,22 @@ plpython_inline_handler(PG_FUNCTION_ARGS)
345346
/*
346347
* Push execution context onto stack. It is important that this get
347348
* popped again, so avoid putting anything that could throw error between
348-
* here and the PG_TRY. (plpython_inline_error_callback doesn't currently
349-
* need the stack entry, but for consistency with plpython_call_handler we
350-
* do it in this order.)
349+
* here and the PG_TRY.
351350
*/
352351
exec_ctx=PLy_push_execution_context();
353352

354-
/*
355-
* Setup error traceback support for ereport()
356-
*/
357-
plerrcontext.callback=plpython_inline_error_callback;
358-
plerrcontext.previous=error_context_stack;
359-
error_context_stack=&plerrcontext;
360-
361353
PG_TRY();
362354
{
355+
/*
356+
* Setup error traceback support for ereport().
357+
* plpython_inline_error_callback doesn't currently need exec_ctx, but
358+
* for consistency with plpython_call_handler we do it the same way.
359+
*/
360+
plerrcontext.callback=plpython_inline_error_callback;
361+
plerrcontext.arg=exec_ctx;
362+
plerrcontext.previous=error_context_stack;
363+
error_context_stack=&plerrcontext;
364+
363365
PLy_procedure_compile(&proc,codeblock->source_text);
364366
exec_ctx->curr_proc=&proc;
365367
PLy_exec_function(&fake_fcinfo,&proc);
@@ -373,9 +375,7 @@ plpython_inline_handler(PG_FUNCTION_ARGS)
373375
}
374376
PG_END_TRY();
375377

376-
/* Pop the error context stack */
377-
error_context_stack=plerrcontext.previous;
378-
/* ... and then the execution context */
378+
/* Destroy the execution context */
379379
PLy_pop_execution_context();
380380

381381
/* Now clean up the transient procedure we made */
@@ -403,7 +403,7 @@ PLy_procedure_is_trigger(Form_pg_proc procStruct)
403403
staticvoid
404404
plpython_error_callback(void*arg)
405405
{
406-
PLyExecutionContext*exec_ctx=PLy_current_execution_context();
406+
PLyExecutionContext*exec_ctx=(PLyExecutionContext*)arg;
407407

408408
if (exec_ctx->curr_proc)
409409
errcontext("PL/Python function \"%s\"",

‎src/pl/plpython/plpy_procedure.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,7 @@ init_procedure_caches(void)
4747
}
4848

4949
/*
50-
* Get the name of the last procedure called by the backend (the
51-
* innermost, if a plpython procedure call calls the backend and the
52-
* backend calls another plpython procedure).
50+
* PLy_procedure_name: get the name of the specified procedure.
5351
*
5452
* NB: this returns the SQL name, not the internal Python procedure name
5553
*/

‎src/pl/plpython/sql/plpython_error.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,3 +328,19 @@ EXCEPTION WHEN SQLSTATE 'SILLY' THEN
328328
-- NOOP
329329
END
330330
$$ LANGUAGE plpgsql;
331+
332+
/* test the context stack trace for nested execution levels
333+
*/
334+
CREATEFUNCTIONnotice_innerfunc() RETURNSintAS $$
335+
plpy.execute("DO LANGUAGE plpythonu $x$ plpy.notice('inside DO') $x$")
336+
return1
337+
$$ LANGUAGE plpythonu;
338+
339+
CREATEFUNCTIONnotice_outerfunc() RETURNSintAS $$
340+
plpy.execute("SELECT notice_innerfunc()")
341+
return1
342+
$$ LANGUAGE plpythonu;
343+
344+
\set SHOW_CONTEXT always
345+
346+
SELECT notice_outerfunc();

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp