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

Commitdfa4baf

Browse files
committed
Run the postmaster's signal handlers without SA_RESTART.
The postmaster keeps signals blocked everywhere except while waitingfor something to happen in ServerLoop(). The code expects that theselect(2) will be cancelled with EINTR if an interrupt occurs; withoutthat, followup actions that should be performed by ServerLoop() itselfwill be delayed. However, some platforms interpret the SA_RESTARTsignal flag as meaning that they should restart rather than cancelthe select(2). Worse yet, some of them restart it with the originaltimeout delay, meaning that a steady stream of signal interrupts canprevent ServerLoop() from iterating at all if there are no incomingconnection requests.Observable symptoms of this, on an affected platform such as HPUX 10,include extremely slow parallel query startup (possibly as much as30 seconds) and failure to update timestamps on the postmaster's socketsand lockfiles when no new connections arrive for a long time.We can fix this by running the postmaster's signal handlers withoutSA_RESTART. That would be quite a scary change if the range of codewhere signals are accepted weren't so tiny, but as it is, it seemssafe enough. (Note that postmaster children do, and must, reset allthe handlers before unblocking signals; so this change should notaffect any child process.)There is talk of rewriting the postmaster to use a WaitEventSet andnot do signal response work in signal handlers, at which point it mightbe appropriate to revert this patch. But that's not happening beforev11 at the earliest.Back-patch to 9.6. The problem exists much further back, but theworst symptom arises only in connection with parallel query, so itdoes not seem worth taking any portability risks in older branches.Discussion:https://postgr.es/m/9205.1492833041@sss.pgh.pa.us
1 parent63f64d2 commitdfa4baf

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

‎src/backend/postmaster/postmaster.c

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,15 @@ PostmasterMain(int argc, char *argv[])
603603
/*
604604
* Set up signal handlers for the postmaster process.
605605
*
606+
* In the postmaster, we want to install non-ignored handlers *without*
607+
* SA_RESTART. This is because they'll be blocked at all times except
608+
* when ServerLoop is waiting for something to happen, and during that
609+
* window, we want signals to exit the select(2) wait so that ServerLoop
610+
* can respond if anything interesting happened. On some platforms,
611+
* signals marked SA_RESTART would not cause the select() wait to end.
612+
* Child processes will generally want SA_RESTART, but we expect them to
613+
* set up their own handlers before unblocking signals.
614+
*
606615
* CAUTION: when changing this list, check for side-effects on the signal
607616
* handling setup of child processes. See tcop/postgres.c,
608617
* bootstrap/bootstrap.c, postmaster/bgwriter.c, postmaster/walwriter.c,
@@ -613,16 +622,20 @@ PostmasterMain(int argc, char *argv[])
613622
pqinitmask();
614623
PG_SETMASK(&BlockSig);
615624

616-
pqsignal(SIGHUP,SIGHUP_handler);/* reread config file and have
617-
* children do same */
618-
pqsignal(SIGINT,pmdie);/* send SIGTERM and shut down */
619-
pqsignal(SIGQUIT,pmdie);/* send SIGQUIT and die */
620-
pqsignal(SIGTERM,pmdie);/* wait for children and shut down */
625+
pqsignal_no_restart(SIGHUP,SIGHUP_handler);/* reread config file
626+
* and have children do
627+
* same */
628+
pqsignal_no_restart(SIGINT,pmdie);/* send SIGTERM and shut down */
629+
pqsignal_no_restart(SIGQUIT,pmdie);/* send SIGQUIT and die */
630+
pqsignal_no_restart(SIGTERM,pmdie);/* wait for children and shut
631+
* down */
621632
pqsignal(SIGALRM,SIG_IGN);/* ignored */
622633
pqsignal(SIGPIPE,SIG_IGN);/* ignored */
623-
pqsignal(SIGUSR1,sigusr1_handler);/* message from child process */
624-
pqsignal(SIGUSR2,dummy_handler);/* unused, reserve for children */
625-
pqsignal(SIGCHLD,reaper);/* handle child termination */
634+
pqsignal_no_restart(SIGUSR1,sigusr1_handler);/* message from child
635+
* process */
636+
pqsignal_no_restart(SIGUSR2,dummy_handler);/* unused, reserve for
637+
* children */
638+
pqsignal_no_restart(SIGCHLD,reaper);/* handle child termination */
626639
pqsignal(SIGTTIN,SIG_IGN);/* ignored */
627640
pqsignal(SIGTTOU,SIG_IGN);/* ignored */
628641
/* ignore SIGXFSZ, so that ulimit violations work like disk full */

‎src/include/port.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,11 @@ extern intpg_mkdir_p(char *path, int omode);
462462
/* port/pqsignal.c */
463463
typedefvoid (*pqsigfunc) (intsigno);
464464
externpqsigfuncpqsignal(intsigno,pqsigfuncfunc);
465+
#ifndefWIN32
466+
externpqsigfuncpqsignal_no_restart(intsigno,pqsigfuncfunc);
467+
#else
468+
#definepqsignal_no_restart(signo,func) pqsignal(signo, func)
469+
#endif
465470

466471
/* port/quotes.c */
467472
externchar*escape_single_quotes_ascii(constchar*src);

‎src/port/pqsignal.c

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#if !defined(WIN32)|| defined(FRONTEND)
3333

3434
/*
35-
* Set up a signal handler for signal "signo"
35+
* Set up a signal handler, with SA_RESTART, for signal "signo"
3636
*
3737
* Returns the previous handler.
3838
*/
@@ -58,4 +58,33 @@ pqsignal(int signo, pqsigfunc func)
5858
#endif
5959
}
6060

61+
/*
62+
* Set up a signal handler, without SA_RESTART, for signal "signo"
63+
*
64+
* Returns the previous handler.
65+
*
66+
* On Windows, this would be identical to pqsignal(), so don't bother.
67+
*/
68+
#ifndefWIN32
69+
70+
pqsigfunc
71+
pqsignal_no_restart(intsigno,pqsigfuncfunc)
72+
{
73+
structsigactionact,
74+
oact;
75+
76+
act.sa_handler=func;
77+
sigemptyset(&act.sa_mask);
78+
act.sa_flags=0;
79+
#ifdefSA_NOCLDSTOP
80+
if (signo==SIGCHLD)
81+
act.sa_flags |=SA_NOCLDSTOP;
82+
#endif
83+
if (sigaction(signo,&act,&oact)<0)
84+
returnSIG_ERR;
85+
returnoact.sa_handler;
86+
}
87+
88+
#endif/* !WIN32 */
89+
6190
#endif/* !defined(WIN32) || defined(FRONTEND) */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp