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

Commit2e211c1

Browse files
committed
Make timeout.c more robust against missed timer interrupts.
Commit09cf1d5 taught schedule_alarm() to not do anything ifthe next requested event is after when we expect the next interruptto fire. However, if somehow an interrupt gets lost, we'll continueto not do anything indefinitely, even after the "next interrupt" timeis obviously in the past. Thus, one missed interrupt can breaktimeout scheduling for the life of the session. Michael Harrisreported a scenario where a bug in a user-defined function caused thisto happen, so you don't even need to assume kernel bugs exist to thinkthis is worth fixing. We can make things more robust at little costby detecting the case where signal_due_at is before "now" and forcinga new setitimer call to occur. This isn't a completely bulletprooffix of course; but in our typical usage pattern where we frequently settimeouts and clear them before they are reached, the interrupt willget re-enabled after at most one timeout interval, which with a littleluck will be before we really need it.While here, let's mark signal_due_at as volatile, since the signalhandler can both examine and set it. I'm not sure there's anyactual risk given that signal_pending is already volatile, butit's surely questionable.Backpatch to v14 where this logic came in.Michael Harris and Tom LaneDiscussion:https://postgr.es/m/CADofcAWbMrvgwSMqO4iG_iD3E2v8ZUrC-_crB41my=VMM02-CA@mail.gmail.com
1 parent5f00ef0 commit2e211c1

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

‎src/backend/utils/misc/timeout.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ static volatile sig_atomic_t alarm_enabled = false;
7070

7171
/*
7272
* State recording if and when we next expect the interrupt to fire.
73+
* (signal_due_at is valid only when signal_pending is true.)
7374
* Note that the signal handler will unconditionally reset signal_pending to
7475
* false, so that can change asynchronously even when alarm_enabled is false.
7576
*/
7677
staticvolatilesig_atomic_tsignal_pending= false;
77-
staticTimestampTzsignal_due_at=0;/* valid only when signal_pending */
78+
staticvolatileTimestampTzsignal_due_at=0;
7879

7980

8081
/*****************************************************************************
@@ -214,10 +215,22 @@ schedule_alarm(TimestampTz now)
214215

215216
MemSet(&timeval,0,sizeof(structitimerval));
216217

218+
/*
219+
* If we think there's a signal pending, but current time is more than
220+
* 10ms past when the signal was due, then assume that the timeout
221+
* request got lost somehow; clear signal_pending so that we'll reset
222+
* the interrupt request below. (10ms corresponds to the worst-case
223+
* timeout granularity on modern systems.) It won't hurt us if the
224+
* interrupt does manage to fire between now and when we reach the
225+
* setitimer() call.
226+
*/
227+
if (signal_pending&&now>signal_due_at+10*1000)
228+
signal_pending= false;
229+
217230
/*
218231
* Get the time remaining till the nearest pending timeout. If it is
219-
* negative, assume that we somehow missed an interrupt, andforce
220-
* signal_pending off. This gives usa chance to recover if the
232+
* negative, assume that we somehow missed an interrupt, andclear
233+
* signal_pending. This gives usanother chance to recover if the
221234
* kernel drops a timeout request for some reason.
222235
*/
223236
nearest_timeout=active_timeouts[0]->fin_time;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp