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

Commit8b53dba

Browse files
committed
In the postmaster, rely on the signal infrastructure to block signals.
POSIX sigaction(2) can be told to block a set of signals while asignal handler executes. Make use of that instead of manuallyblocking and unblocking signals in the postmaster's signal handlers.This should save a few cycles, but more importantly it preventsrecursive invocation of signal handlers when many signals arrive inclose succession. (Assuming that the platform's signal infrastructureis designed to avoid consuming stack space in that case, but this isdemonstrably true at least on Linux.) The existing code has been seento recurse to the point of stack overflow, either in the postmasteror in a forked-off child.Back-patch of commit9abb2bf. At the time, we'd only seen excesspostmaster stack consumption in the buildfarm; but we now have auser report of it, and that commit has aged enough to have a fairamount of confidence that it doesn't break anything.This still doesn't change anything about the way that it works onWindows. Perhaps someone else would like to fix that?Per bug #16673 from David Geier. Back-patch to 9.6. Althoughthe problem exists in principle before that, we've only seen itactually materialize in connection with heavy use of parallelworkers, so it doesn't seem necessary to do anything in 9.5;and the relevant code is different there, too.Discussion:https://postgr.es/m/16673-d278c604f8e34ec0@postgresql.orgDiscussion:https://postgr.es/m/14878.1570820201@sss.pgh.pa.us
1 parent72b1574 commit8b53dba

File tree

5 files changed

+116
-57
lines changed

5 files changed

+116
-57
lines changed

‎src/backend/libpq/pqsignal.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,52 @@ pqinitmask(void)
9595
sigdelset(&StartupBlockSig,SIGALRM);
9696
#endif
9797
}
98+
99+
/*
100+
* Set up a postmaster signal handler for signal "signo"
101+
*
102+
* Returns the previous handler.
103+
*
104+
* This is used only in the postmaster, which has its own odd approach to
105+
* signal handling. For signals with handlers, we block all signals for the
106+
* duration of signal handler execution. We also do not set the SA_RESTART
107+
* flag; this should be safe given the tiny range of code in which the
108+
* postmaster ever unblocks signals.
109+
*
110+
* pqinitmask() must have been invoked previously.
111+
*
112+
* On Windows, this function is just an alias for pqsignal()
113+
* (and note that it's calling the code in src/backend/port/win32/signal.c,
114+
* not src/port/pqsignal.c). On that platform, the postmaster's signal
115+
* handlers still have to block signals for themselves.
116+
*/
117+
pqsigfunc
118+
pqsignal_pm(intsigno,pqsigfuncfunc)
119+
{
120+
#ifndefWIN32
121+
structsigactionact,
122+
oact;
123+
124+
act.sa_handler=func;
125+
if (func==SIG_IGN||func==SIG_DFL)
126+
{
127+
/* in these cases, act the same as pqsignal() */
128+
sigemptyset(&act.sa_mask);
129+
act.sa_flags=SA_RESTART;
130+
}
131+
else
132+
{
133+
act.sa_mask=BlockSig;
134+
act.sa_flags=0;
135+
}
136+
#ifdefSA_NOCLDSTOP
137+
if (signo==SIGCHLD)
138+
act.sa_flags |=SA_NOCLDSTOP;
139+
#endif
140+
if (sigaction(signo,&act,&oact)<0)
141+
returnSIG_ERR;
142+
returnoact.sa_handler;
143+
#else/* WIN32 */
144+
returnpqsignal(signo,func);
145+
#endif
146+
}

‎src/backend/postmaster/postmaster.c

Lines changed: 64 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -618,14 +618,25 @@ PostmasterMain(int argc, char *argv[])
618618
/*
619619
* Set up signal handlers for the postmaster process.
620620
*
621-
* In the postmaster, we want to install non-ignored handlers *without*
622-
* SA_RESTART. This is because they'll be blocked at all times except
623-
* when ServerLoop is waiting for something to happen, and during that
624-
* window, we want signals to exit the select(2) wait so that ServerLoop
625-
* can respond if anything interesting happened. On some platforms,
626-
* signals marked SA_RESTART would not cause the select() wait to end.
627-
* Child processes will generally want SA_RESTART, but we expect them to
628-
* set up their own handlers before unblocking signals.
621+
* In the postmaster, we use pqsignal_pm() rather than pqsignal() (which
622+
* is used by all child processes and client processes). That has a
623+
* couple of special behaviors:
624+
*
625+
* 1. Except on Windows, we tell sigaction() to block all signals for the
626+
* duration of the signal handler. This is faster than our old approach
627+
* of blocking/unblocking explicitly in the signal handler, and it should
628+
* also prevent excessive stack consumption if signals arrive quickly.
629+
*
630+
* 2. We do not set the SA_RESTART flag. This is because signals will be
631+
* blocked at all times except when ServerLoop is waiting for something to
632+
* happen, and during that window, we want signals to exit the select(2)
633+
* wait so that ServerLoop can respond if anything interesting happened.
634+
* On some platforms, signals marked SA_RESTART would not cause the
635+
* select() wait to end.
636+
*
637+
* Child processes will generally want SA_RESTART, so pqsignal() sets that
638+
* flag. We expect children to set up their own handlers before
639+
* unblocking signals.
629640
*
630641
* CAUTION: when changing this list, check for side-effects on the signal
631642
* handling setup of child processes. See tcop/postgres.c,
@@ -637,18 +648,16 @@ PostmasterMain(int argc, char *argv[])
637648
pqinitmask();
638649
PG_SETMASK(&BlockSig);
639650

640-
pqsignal_no_restart(SIGHUP,SIGHUP_handler);/* reread config file and
641-
* have children do same */
642-
pqsignal_no_restart(SIGINT,pmdie);/* send SIGTERM and shut down */
643-
pqsignal_no_restart(SIGQUIT,pmdie);/* send SIGQUIT and die */
644-
pqsignal_no_restart(SIGTERM,pmdie);/* wait for children and shut down */
645-
pqsignal(SIGALRM,SIG_IGN);/* ignored */
646-
pqsignal(SIGPIPE,SIG_IGN);/* ignored */
647-
pqsignal_no_restart(SIGUSR1,sigusr1_handler);/* message from child
648-
* process */
649-
pqsignal_no_restart(SIGUSR2,dummy_handler);/* unused, reserve for
650-
* children */
651-
pqsignal_no_restart(SIGCHLD,reaper);/* handle child termination */
651+
pqsignal_pm(SIGHUP,SIGHUP_handler);/* reread config file and have
652+
* children do same */
653+
pqsignal_pm(SIGINT,pmdie);/* send SIGTERM and shut down */
654+
pqsignal_pm(SIGQUIT,pmdie);/* send SIGQUIT and die */
655+
pqsignal_pm(SIGTERM,pmdie);/* wait for children and shut down */
656+
pqsignal_pm(SIGALRM,SIG_IGN);/* ignored */
657+
pqsignal_pm(SIGPIPE,SIG_IGN);/* ignored */
658+
pqsignal_pm(SIGUSR1,sigusr1_handler);/* message from child process */
659+
pqsignal_pm(SIGUSR2,dummy_handler);/* unused, reserve for children */
660+
pqsignal_pm(SIGCHLD,reaper);/* handle child termination */
652661

653662
/*
654663
* No other place in Postgres should touch SIGTTIN/SIGTTOU handling. We
@@ -658,15 +667,15 @@ PostmasterMain(int argc, char *argv[])
658667
* child processes should just allow the inherited settings to stand.
659668
*/
660669
#ifdefSIGTTIN
661-
pqsignal(SIGTTIN,SIG_IGN);/* ignored */
670+
pqsignal_pm(SIGTTIN,SIG_IGN);/* ignored */
662671
#endif
663672
#ifdefSIGTTOU
664-
pqsignal(SIGTTOU,SIG_IGN);/* ignored */
673+
pqsignal_pm(SIGTTOU,SIG_IGN);/* ignored */
665674
#endif
666675

667676
/* ignore SIGXFSZ, so that ulimit violations work like disk full */
668677
#ifdefSIGXFSZ
669-
pqsignal(SIGXFSZ,SIG_IGN);/* ignored */
678+
pqsignal_pm(SIGXFSZ,SIG_IGN);/* ignored */
670679
#endif
671680

672681
/*
@@ -2655,7 +2664,13 @@ SIGHUP_handler(SIGNAL_ARGS)
26552664
{
26562665
intsave_errno=errno;
26572666

2667+
/*
2668+
* We rely on the signal mechanism to have blocked all signals ... except
2669+
* on Windows, which lacks sigaction(), so we have to do it manually.
2670+
*/
2671+
#ifdefWIN32
26582672
PG_SETMASK(&BlockSig);
2673+
#endif
26592674

26602675
if (Shutdown <=SmartShutdown)
26612676
{
@@ -2715,7 +2730,9 @@ SIGHUP_handler(SIGNAL_ARGS)
27152730
#endif
27162731
}
27172732

2733+
#ifdefWIN32
27182734
PG_SETMASK(&UnBlockSig);
2735+
#endif
27192736

27202737
errno=save_errno;
27212738
}
@@ -2729,7 +2746,13 @@ pmdie(SIGNAL_ARGS)
27292746
{
27302747
intsave_errno=errno;
27312748

2749+
/*
2750+
* We rely on the signal mechanism to have blocked all signals ... except
2751+
* on Windows, which lacks sigaction(), so we have to do it manually.
2752+
*/
2753+
#ifdefWIN32
27322754
PG_SETMASK(&BlockSig);
2755+
#endif
27332756

27342757
ereport(DEBUG2,
27352758
(errmsg_internal("postmaster received signal %d",
@@ -2858,7 +2881,9 @@ pmdie(SIGNAL_ARGS)
28582881
break;
28592882
}
28602883

2884+
#ifdefWIN32
28612885
PG_SETMASK(&UnBlockSig);
2886+
#endif
28622887

28632888
errno=save_errno;
28642889
}
@@ -2873,7 +2898,13 @@ reaper(SIGNAL_ARGS)
28732898
intpid;/* process id of dead child process */
28742899
intexitstatus;/* its exit status */
28752900

2901+
/*
2902+
* We rely on the signal mechanism to have blocked all signals ... except
2903+
* on Windows, which lacks sigaction(), so we have to do it manually.
2904+
*/
2905+
#ifdefWIN32
28762906
PG_SETMASK(&BlockSig);
2907+
#endif
28772908

28782909
ereport(DEBUG4,
28792910
(errmsg_internal("reaping dead processes")));
@@ -3176,7 +3207,9 @@ reaper(SIGNAL_ARGS)
31763207
PostmasterStateMachine();
31773208

31783209
/* Done with signal handler */
3210+
#ifdefWIN32
31793211
PG_SETMASK(&UnBlockSig);
3212+
#endif
31803213

31813214
errno=save_errno;
31823215
}
@@ -5110,7 +5143,13 @@ sigusr1_handler(SIGNAL_ARGS)
51105143
{
51115144
intsave_errno=errno;
51125145

5146+
/*
5147+
* We rely on the signal mechanism to have blocked all signals ... except
5148+
* on Windows, which lacks sigaction(), so we have to do it manually.
5149+
*/
5150+
#ifdefWIN32
51135151
PG_SETMASK(&BlockSig);
5152+
#endif
51145153

51155154
/* Process background worker state change. */
51165155
if (CheckPostmasterSignal(PMSIGNAL_BACKGROUND_WORKER_CHANGE))
@@ -5270,7 +5309,9 @@ sigusr1_handler(SIGNAL_ARGS)
52705309
signal_child(StartupPID,SIGUSR2);
52715310
}
52725311

5312+
#ifdefWIN32
52735313
PG_SETMASK(&UnBlockSig);
5314+
#endif
52745315

52755316
errno=save_errno;
52765317
}

‎src/include/libpq/pqsignal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,7 @@ extern sigset_t UnBlockSig,
3636

3737
externvoidpqinitmask(void);
3838

39+
/* pqsigfunc is declared in src/include/port.h */
40+
externpqsigfuncpqsignal_pm(intsigno,pqsigfuncfunc);
41+
3942
#endif/* PQSIGNAL_H */

‎src/include/port.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,6 @@ extern intpg_mkdir_p(char *path, int omode);
524524
/* port/pqsignal.c */
525525
typedefvoid (*pqsigfunc) (intsigno);
526526
externpqsigfuncpqsignal(intsigno,pqsigfuncfunc);
527-
#ifndefWIN32
528-
externpqsigfuncpqsignal_no_restart(intsigno,pqsigfuncfunc);
529-
#else
530-
#definepqsignal_no_restart(signo,func) pqsignal(signo, func)
531-
#endif
532527

533528
/* port/quotes.c */
534529
externchar*escape_single_quotes_ascii(constchar*src);

‎src/port/pqsignal.c

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,33 +58,4 @@ 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-
9061
#endif/* !defined(WIN32) || defined(FRONTEND) */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp