1
0
mirror of https://github.com/postgres/postgres.git synced 2025-05-05 09:19:17 +03:00

Avoid lockup of a parallel worker when reporting a long error message.

Because sigsetjmp() will restore the initial state with signals blocked,
the code path in bgworker.c for reporting an error and exiting would
execute that way.  Usually this is fairly harmless; but if a parallel
worker had an error message exceeding the shared-memory communication
buffer size (16K) it would lock up, because it would wait for a
resume-sending signal from its parallel leader which it would never
detect.

To fix, just unblock signals at the appropriate point.

This can be shown to fail back to 9.6.  The lack of parallel query
infrastructure makes it difficult to provide a simple test case for
9.5; but I'm pretty sure the issue exists in some form there as well,
so apply the code change there too.

Vignesh C, reviewed by Bharath Rupireddy, Robert Haas, and myself

Discussion: https://postgr.es/m/CALDaNm1d1hHPZUg3xU4XjtWBOLCrA+-2cJcLpw-cePZ=GgDVfA@mail.gmail.com
This commit is contained in:
Tom Lane 2020-09-03 16:52:09 -04:00
parent 579a022ca1
commit 2a938c7935
3 changed files with 14 additions and 5 deletions

View File

@ -758,7 +758,7 @@ StartBackgroundWorker(void)
/*
* If an exception is encountered, processing resumes here.
*
* See notes in postgres.c about the design of this coding.
* We just need to clean up, report the error, and go away.
*/
if (sigsetjmp(local_sigjmp_buf, 1) != 0)
{
@ -768,7 +768,14 @@ StartBackgroundWorker(void)
/* Prevent interrupts while cleaning up */
HOLD_INTERRUPTS();
/* Report the error to the server log */
/*
* sigsetjmp will have blocked all signals, but we may need to accept
* signals while communicating with our parallel leader. Once we've
* done HOLD_INTERRUPTS() it should be safe to unblock signals.
*/
BackgroundWorkerUnblockSignals();
/* Report the error to the parallel leader and the server log */
EmitErrorReport();
/*

File diff suppressed because one or more lines are too long

View File

@ -255,6 +255,7 @@ EXECUTE pstmt('1', make_some_array(1,2));
DEALLOCATE pstmt;
-- provoke error in worker
select stringu1::int2 from tenk1 where unique1 = 1;
-- (make the error message long enough to require multiple bufferloads)
select (stringu1 || repeat('abcd', 5000))::int2 from tenk1 where unique1 = 1;
rollback;