Skip to content

Commit a64ca63

Browse files
committed
Use WaitLatch, not pg_usleep, for delaying in pg_sleep().
This avoids platform-dependent behavior wherein pg_sleep() might fail to be interrupted by statement timeout, query cancel, SIGTERM, etc. Also, since there's no reason to wake up once a second any more, we can reduce the power consumption of a sleeping backend a tad. Back-patch to 9.3, since use of SA_RESTART for SIGALRM makes this a bigger issue than it used to be.
1 parent f69aece commit a64ca63

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/backend/utils/adt/misc.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -384,16 +384,16 @@ pg_sleep(PG_FUNCTION_ARGS)
384384
float8 endtime;
385385

386386
/*
387-
* We break the requested sleep into segments of no more than 1 second, to
388-
* put an upper bound on how long it will take us to respond to a cancel
389-
* or die interrupt. (Note that pg_usleep is interruptible by signals on
390-
* some platforms but not others.) Also, this method avoids exposing
391-
* pg_usleep's upper bound on allowed delays.
387+
* We sleep using WaitLatch, to ensure that we'll wake up promptly if an
388+
* important signal (such as SIGALRM or SIGINT) arrives. Because
389+
* WaitLatch's upper limit of delay is INT_MAX milliseconds, and the user
390+
* might ask for more than that, we sleep for at most 10 minutes and then
391+
* loop.
392392
*
393393
* By computing the intended stop time initially, we avoid accumulation of
394394
* extra delay across multiple sleeps. This also ensures we won't delay
395-
* less than the specified time if pg_usleep is interrupted by other
396-
* signals such as SIGHUP.
395+
* less than the specified time when WaitLatch is terminated early by a
396+
* non-query-cancelling signal such as SIGHUP.
397397
*/
398398

399399
#ifdef HAVE_INT64_TIMESTAMP
@@ -407,15 +407,22 @@ pg_sleep(PG_FUNCTION_ARGS)
407407
for (;;)
408408
{
409409
float8 delay;
410+
long delay_ms;
410411

411412
CHECK_FOR_INTERRUPTS();
413+
412414
delay = endtime - GetNowFloat();
413-
if (delay >= 1.0)
414-
pg_usleep(1000000L);
415+
if (delay >= 600.0)
416+
delay_ms = 600000;
415417
else if (delay > 0.0)
416-
pg_usleep((long) ceil(delay * 1000000.0));
418+
delay_ms = (long) ceil(delay * 1000.0);
417419
else
418420
break;
421+
422+
(void) WaitLatch(&MyProc->procLatch,
423+
WL_LATCH_SET | WL_TIMEOUT,
424+
delay_ms);
425+
ResetLatch(&MyProc->procLatch);
419426
}
420427

421428
PG_RETURN_VOID();

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy