提交 0015787e 编写于 作者: P Pengzhou Tang

Fix SIGSEGV caused by incorrect setting of error_context_stack within external_endscan

Within external_beginscan(), scan->errcontext.previous may link to local error contexts such as spierrcontext, if errors occur, abort routines call external_endscan() to set global value error_context_stack to those local error contexts whose stack are not exist anymore, so everytime elog() or ereport() are called, a SIGSEGV occurs. To avoid this, setting up and restoring error_context_stack within a single function.
上级 65cfa7ef
......@@ -279,11 +279,6 @@ external_beginscan(Relation relation, Index scanrelid, uint32 scancounter,
scan->fs_formatter->fmt_perrow_ctx = scan->fs_pstate->rowcontext;
}
/* Set up callback to identify error line number */
scan->errcontext.callback = external_scan_error_callback;
scan->errcontext.arg = (void *) scan->fs_pstate;
scan->errcontext.previous = error_context_stack;
/* pgstat_initstats(relation); */
return scan;
......@@ -405,11 +400,6 @@ external_endscan(FileScanDesc scan)
scan->fs_pstate = NULL;
}
/*
* clean up error context
*/
error_context_stack = scan->errcontext.previous;
PG_TRY();
{
/*
......@@ -1200,10 +1190,16 @@ externalgettup(FileScanDesc scan,
{
CopyState pstate = scan->fs_pstate;
bool custom = pstate->custom;
HeapTuple tup = NULL;
ErrorContextCallback externalscan_error_context;
Assert(ScanDirectionIsForward(dir));
error_context_stack = &scan->errcontext;
externalscan_error_context.callback = external_scan_error_callback;
externalscan_error_context.arg = (void *) scan->fs_pstate;
externalscan_error_context.previous = error_context_stack;
error_context_stack = &externalscan_error_context;
if (!scan->fs_inited)
{
......@@ -1217,10 +1213,14 @@ externalgettup(FileScanDesc scan,
}
if (!custom)
return externalgettup_defined(scan); /* text/csv */
tup = externalgettup_defined(scan); /* text/csv */
else
return externalgettup_custom(scan); /* custom */
tup = externalgettup_custom(scan); /* custom */
/* Restore the previous error callback */
error_context_stack = externalscan_error_context.previous;
return tup;
}
/*
......
......@@ -118,7 +118,6 @@ typedef struct FileScanDescData
FmgrInfo *in_functions;
Oid *typioparams;
Oid in_func_oid;
ErrorContextCallback errcontext;
/* current file scan state */
bool fs_inited; /* false = scan not init'd yet */
......
......@@ -1421,3 +1421,32 @@ FORMAT 'csv';
-- drop temp external table
DROP EXTERNAL TABLE IF EXISTS serial;
-- External table query within plpgSQL function get error
CREATE EXTERNAL TABLE exttab_error_context_callback(c1 int, c2 int)
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT';
CREATE or REPLACE FUNCTION exttab_error_context_callback_func()
RETURNS SETOF INTEGER
AS
$$
DECLARE
ret INTEGER;
BEGIN
FOR ret IN
SELECT c2 from exttab_error_context_callback
LOOP
RETURN NEXT ret;
END LOOP;
END
$$
LANGUAGE plpgSQL READS SQL DATA;
SET gp_log_gang TO DEBUG;
SELECT * FROM exttab_error_context_callback_func();
SET gp_log_gang TO DEFAULT;
DROP FUNCTION exttab_error_context_callback_func();
DROP EXTERNAL TABLE exttab_error_context_callback;
......@@ -2886,3 +2886,29 @@ FORMAT 'csv';
NOTICE: CREATE EXTERNAL TABLE will create implicit sequence "serial_a_seq" for serial column "serial.a"
-- drop temp external table
DROP EXTERNAL TABLE IF EXISTS serial;
-- External table query within plpgSQL function get error
CREATE EXTERNAL TABLE exttab_error_context_callback(c1 int, c2 int)
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab.data') FORMAT 'TEXT';
CREATE or REPLACE FUNCTION exttab_error_context_callback_func()
RETURNS SETOF INTEGER
AS
$$
DECLARE
ret INTEGER;
BEGIN
FOR ret IN
SELECT c2 from exttab_error_context_callback
LOOP
RETURN NEXT ret;
END LOOP;
END
$$
LANGUAGE plpgSQL READS SQL DATA;
SET gp_log_gang TO DEBUG;
SELECT * FROM exttab_error_context_callback_func();
ERROR: missing data for column "c2" (seg1 slice2 @hostname@:25532 pid=20960)
DETAIL: External table exttab_error_context_callback, line 1 of file://@hostname@@abs_srcdir@/data/exttab.data: "1|1_number"
CONTEXT: PL/pgSQL function "exttab_error_context_callback_func" line 4 at FOR over SELECT rows
SET gp_log_gang TO DEFAULT;
DROP FUNCTION exttab_error_context_callback_func();
DROP EXTERNAL TABLE exttab_error_context_callback;
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册