PostgreSQL Source Code  git master
timeout.c File Reference
#include "postgres.h"
#include <sys/time.h>
#include "miscadmin.h"
#include "storage/proc.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
Include dependency graph for timeout.c:

Go to the source code of this file.

Data Structures

struct  timeout_params
 

Macros

#define disable_alarm()   (alarm_enabled = false)
 
#define enable_alarm()   (alarm_enabled = true)
 

Typedefs

typedef struct timeout_params timeout_params
 

Functions

static int find_active_timeout (TimeoutId id)
 
static void insert_timeout (TimeoutId id, int index)
 
static void remove_timeout_index (int index)
 
static void enable_timeout (TimeoutId id, TimestampTz now, TimestampTz fin_time)
 
static void schedule_alarm (TimestampTz now)
 
static void handle_sig_alarm (SIGNAL_ARGS)
 
void InitializeTimeouts (void)
 
TimeoutId RegisterTimeout (TimeoutId id, timeout_handler_proc handler)
 
void reschedule_timeouts (void)
 
void enable_timeout_after (TimeoutId id, int delay_ms)
 
void enable_timeout_at (TimeoutId id, TimestampTz fin_time)
 
void enable_timeouts (const EnableTimeoutParams *timeouts, int count)
 
void disable_timeout (TimeoutId id, bool keep_indicator)
 
void disable_timeouts (const DisableTimeoutParams *timeouts, int count)
 
void disable_all_timeouts (bool keep_indicators)
 
bool get_timeout_active (TimeoutId id)
 
bool get_timeout_indicator (TimeoutId id, bool reset_indicator)
 
TimestampTz get_timeout_start_time (TimeoutId id)
 
TimestampTz get_timeout_finish_time (TimeoutId id)
 

Variables

static timeout_params all_timeouts [MAX_TIMEOUTS]
 
static bool all_timeouts_initialized = false
 
static volatile int num_active_timeouts = 0
 
static timeout_params *volatile active_timeouts [MAX_TIMEOUTS]
 
static volatile sig_atomic_t alarm_enabled = false
 

Macro Definition Documentation

◆ disable_alarm

◆ enable_alarm

#define enable_alarm ( )    (alarm_enabled = true)

Definition at line 66 of file timeout.c.

Referenced by schedule_alarm().

Typedef Documentation

◆ timeout_params

Function Documentation

◆ disable_all_timeouts()

void disable_all_timeouts ( bool  keep_indicators)

Definition at line 598 of file timeout.c.

References timeout_params::active, disable_alarm, elog, FATAL, i, timeout_params::indicator, ITIMER_REAL, MAX_TIMEOUTS, MemSet, num_active_timeouts, and setitimer().

Referenced by AutoVacLauncherMain(), PostgresMain(), ResolveRecoveryConflictWithBufferPin(), and ResolveRecoveryConflictWithLock().

599 {
600  int i;
601 
602  disable_alarm();
603 
604  /*
605  * Only bother to reset the timer if we think it's active. We could just
606  * let the interrupt happen anyway, but it's probably a bit cheaper to do
607  * setitimer() than to let the useless interrupt happen.
608  */
609  if (num_active_timeouts > 0)
610  {
611  struct itimerval timeval;
612 
613  MemSet(&timeval, 0, sizeof(struct itimerval));
614  if (setitimer(ITIMER_REAL, &timeval, NULL) != 0)
615  elog(FATAL, "could not disable SIGALRM timer: %m");
616  }
617 
619 
620  for (i = 0; i < MAX_TIMEOUTS; i++)
621  {
622  all_timeouts[i].active = false;
623  if (!keep_indicators)
624  all_timeouts[i].indicator = false;
625  }
626 }
#define MemSet(start, val, len)
Definition: c.h:949
#define disable_alarm()
Definition: timeout.c:65
volatile bool indicator
Definition: timeout.c:32
volatile bool active
Definition: timeout.c:31
#define FATAL
Definition: elog.h:52
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
Definition: timer.c:86
#define elog(elevel,...)
Definition: elog.h:214
int i
static volatile int num_active_timeouts
Definition: timeout.c:51
#define ITIMER_REAL
Definition: win32_port.h:181

◆ disable_timeout()

void disable_timeout ( TimeoutId  id,
bool  keep_indicator 
)

Definition at line 532 of file timeout.c.

References timeout_params::active, all_timeouts_initialized, Assert, disable_alarm, find_active_timeout(), GetCurrentTimestamp(), timeout_params::indicator, num_active_timeouts, remove_timeout_index(), schedule_alarm(), and timeout_params::timeout_handler.

Referenced by BackendInitialize(), disable_statement_timeout(), enable_statement_timeout(), PerformAuthentication(), PostgresMain(), ProcSleep(), and StandbyTimeoutHandler().

533 {
534  /* Assert request is sane */
536  Assert(all_timeouts[id].timeout_handler != NULL);
537 
538  /* Disable timeout interrupts for safety. */
539  disable_alarm();
540 
541  /* Find the timeout and remove it from the active list. */
542  if (all_timeouts[id].active)
544 
545  /* Mark it inactive, whether it was active or not. */
546  if (!keep_indicator)
547  all_timeouts[id].indicator = false;
548 
549  /* Reschedule the interrupt, if any timeouts remain active. */
550  if (num_active_timeouts > 0)
552 }
static bool all_timeouts_initialized
Definition: timeout.c:45
static void remove_timeout_index(int index)
Definition: timeout.c:124
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
#define disable_alarm()
Definition: timeout.c:65
volatile bool indicator
Definition: timeout.c:32
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
#define Assert(condition)
Definition: c.h:745
static int find_active_timeout(TimeoutId id)
Definition: timeout.c:83
static volatile int num_active_timeouts
Definition: timeout.c:51

◆ disable_timeouts()

void disable_timeouts ( const DisableTimeoutParams timeouts,
int  count 
)

Definition at line 565 of file timeout.c.

References timeout_params::active, all_timeouts_initialized, Assert, disable_alarm, find_active_timeout(), GetCurrentTimestamp(), i, DisableTimeoutParams::id, timeout_params::indicator, num_active_timeouts, remove_timeout_index(), schedule_alarm(), and timeout_params::timeout_handler.

Referenced by LockErrorCleanup(), and ProcSleep().

566 {
567  int i;
568 
570 
571  /* Disable timeout interrupts for safety. */
572  disable_alarm();
573 
574  /* Cancel the timeout(s). */
575  for (i = 0; i < count; i++)
576  {
577  TimeoutId id = timeouts[i].id;
578 
579  Assert(all_timeouts[id].timeout_handler != NULL);
580 
581  if (all_timeouts[id].active)
583 
584  if (!timeouts[i].keep_indicator)
585  all_timeouts[id].indicator = false;
586  }
587 
588  /* Reschedule the interrupt, if any timeouts remain active. */
589  if (num_active_timeouts > 0)
591 }
static bool all_timeouts_initialized
Definition: timeout.c:45
static void remove_timeout_index(int index)
Definition: timeout.c:124
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
#define disable_alarm()
Definition: timeout.c:65
volatile bool indicator
Definition: timeout.c:32
TimeoutId id
Definition: timeout.h:65
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
#define Assert(condition)
Definition: c.h:745
TimeoutId
Definition: timeout.h:23
static int find_active_timeout(TimeoutId id)
Definition: timeout.c:83
int i
static volatile int num_active_timeouts
Definition: timeout.c:51

◆ enable_timeout()

static void enable_timeout ( TimeoutId  id,
TimestampTz  now,
TimestampTz  fin_time 
)
static

Definition at line 145 of file timeout.c.

References timeout_params::active, all_timeouts_initialized, Assert, timeout_params::fin_time, find_active_timeout(), i, timeout_params::indicator, insert_timeout(), now(), num_active_timeouts, remove_timeout_index(), timeout_params::start_time, and timeout_params::timeout_handler.

Referenced by enable_timeout_after(), enable_timeout_at(), and enable_timeouts().

146 {
147  int i;
148 
149  /* Assert request is sane */
151  Assert(all_timeouts[id].timeout_handler != NULL);
152 
153  /*
154  * If this timeout was already active, momentarily disable it. We
155  * interpret the call as a directive to reschedule the timeout.
156  */
157  if (all_timeouts[id].active)
159 
160  /*
161  * Find out the index where to insert the new timeout. We sort by
162  * fin_time, and for equal fin_time by priority.
163  */
164  for (i = 0; i < num_active_timeouts; i++)
165  {
166  timeout_params *old_timeout = active_timeouts[i];
167 
168  if (fin_time < old_timeout->fin_time)
169  break;
170  if (fin_time == old_timeout->fin_time && id < old_timeout->index)
171  break;
172  }
173 
174  /*
175  * Mark the timeout active, and insert it into the active list.
176  */
177  all_timeouts[id].indicator = false;
179  all_timeouts[id].fin_time = fin_time;
180 
181  insert_timeout(id, i);
182 }
static bool all_timeouts_initialized
Definition: timeout.c:45
static void remove_timeout_index(int index)
Definition: timeout.c:124
TimestampTz fin_time
Definition: timeout.c:38
volatile bool indicator
Definition: timeout.c:32
Definition: type.h:89
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
TimestampTz start_time
Definition: timeout.c:37
static void insert_timeout(TimeoutId id, int index)
Definition: timeout.c:101
#define Assert(condition)
Definition: c.h:745
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:52
static int find_active_timeout(TimeoutId id)
Definition: timeout.c:83
int i
static volatile int num_active_timeouts
Definition: timeout.c:51
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538

◆ enable_timeout_after()

void enable_timeout_after ( TimeoutId  id,
int  delay_ms 
)

Definition at line 435 of file timeout.c.

References disable_alarm, enable_timeout(), timeout_params::fin_time, GetCurrentTimestamp(), now(), schedule_alarm(), and TimestampTzPlusMilliseconds.

Referenced by BackendInitialize(), enable_statement_timeout(), PerformAuthentication(), PostgresMain(), ProcSleep(), and ResolveRecoveryConflictWithBufferPin().

436 {
438  TimestampTz fin_time;
439 
440  /* Disable timeout interrupts for safety. */
441  disable_alarm();
442 
443  /* Queue the timeout at the appropriate time. */
444  now = GetCurrentTimestamp();
445  fin_time = TimestampTzPlusMilliseconds(now, delay_ms);
446  enable_timeout(id, now, fin_time);
447 
448  /* Set the timer interrupt. */
449  schedule_alarm(now);
450 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:65
static void enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
Definition: timeout.c:145
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:56
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538

◆ enable_timeout_at()

void enable_timeout_at ( TimeoutId  id,
TimestampTz  fin_time 
)

Definition at line 460 of file timeout.c.

References disable_alarm, enable_timeout(), GetCurrentTimestamp(), now(), and schedule_alarm().

461 {
463 
464  /* Disable timeout interrupts for safety. */
465  disable_alarm();
466 
467  /* Queue the timeout at the appropriate time. */
468  now = GetCurrentTimestamp();
469  enable_timeout(id, now, fin_time);
470 
471  /* Set the timer interrupt. */
472  schedule_alarm(now);
473 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:65
static void enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
Definition: timeout.c:145
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538

◆ enable_timeouts()

void enable_timeouts ( const EnableTimeoutParams timeouts,
int  count 
)

Definition at line 483 of file timeout.c.

References disable_alarm, elog, enable_timeout(), ERROR, timeout_params::fin_time, GetCurrentTimestamp(), i, EnableTimeoutParams::id, now(), schedule_alarm(), TimestampTzPlusMilliseconds, TMPARAM_AFTER, TMPARAM_AT, and generate_unaccent_rules::type.

Referenced by ProcSleep(), ResolveRecoveryConflictWithBufferPin(), and ResolveRecoveryConflictWithLock().

484 {
486  int i;
487 
488  /* Disable timeout interrupts for safety. */
489  disable_alarm();
490 
491  /* Queue the timeout(s) at the appropriate times. */
492  now = GetCurrentTimestamp();
493 
494  for (i = 0; i < count; i++)
495  {
496  TimeoutId id = timeouts[i].id;
497  TimestampTz fin_time;
498 
499  switch (timeouts[i].type)
500  {
501  case TMPARAM_AFTER:
502  fin_time = TimestampTzPlusMilliseconds(now,
503  timeouts[i].delay_ms);
504  enable_timeout(id, now, fin_time);
505  break;
506 
507  case TMPARAM_AT:
508  enable_timeout(id, now, timeouts[i].fin_time);
509  break;
510 
511  default:
512  elog(ERROR, "unrecognized timeout type %d",
513  (int) timeouts[i].type);
514  break;
515  }
516  }
517 
518  /* Set the timer interrupt. */
519  schedule_alarm(now);
520 }
TimeoutId id
Definition: timeout.h:54
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:65
#define ERROR
Definition: elog.h:43
static void enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
Definition: timeout.c:145
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:56
TimeoutId
Definition: timeout.h:23
#define elog(elevel,...)
Definition: elog.h:214
int i
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538

◆ find_active_timeout()

static int find_active_timeout ( TimeoutId  id)
static

Definition at line 83 of file timeout.c.

References i, and num_active_timeouts.

Referenced by disable_timeout(), disable_timeouts(), and enable_timeout().

84 {
85  int i;
86 
87  for (i = 0; i < num_active_timeouts; i++)
88  {
89  if (active_timeouts[i]->index == id)
90  return i;
91  }
92 
93  return -1;
94 }
Definition: type.h:89
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:52
int i
static volatile int num_active_timeouts
Definition: timeout.c:51

◆ get_timeout_active()

bool get_timeout_active ( TimeoutId  id)

Definition at line 635 of file timeout.c.

References timeout_params::active.

Referenced by disable_statement_timeout(), and enable_statement_timeout().

636 {
637  return all_timeouts[id].active;
638 }
volatile bool active
Definition: timeout.c:31
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44

◆ get_timeout_finish_time()

TimestampTz get_timeout_finish_time ( TimeoutId  id)

Definition at line 682 of file timeout.c.

References timeout_params::fin_time.

Referenced by ProcessInterrupts().

683 {
684  return all_timeouts[id].fin_time;
685 }
TimestampTz fin_time
Definition: timeout.c:38
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44

◆ get_timeout_indicator()

bool get_timeout_indicator ( TimeoutId  id,
bool  reset_indicator 
)

Definition at line 648 of file timeout.c.

References timeout_params::indicator.

Referenced by ProcessInterrupts().

649 {
650  if (all_timeouts[id].indicator)
651  {
652  if (reset_indicator)
653  all_timeouts[id].indicator = false;
654  return true;
655  }
656  return false;
657 }
volatile bool indicator
Definition: timeout.c:32
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44

◆ get_timeout_start_time()

TimestampTz get_timeout_start_time ( TimeoutId  id)

Definition at line 668 of file timeout.c.

References timeout_params::start_time.

Referenced by ProcSleep().

669 {
670  return all_timeouts[id].start_time;
671 }
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
TimestampTz start_time
Definition: timeout.c:37

◆ handle_sig_alarm()

static void handle_sig_alarm ( SIGNAL_ARGS  )
static

Definition at line 265 of file timeout.c.

References alarm_enabled, disable_alarm, timeout_params::fin_time, GetCurrentTimestamp(), HOLD_INTERRUPTS, timeout_params::indicator, MyLatch, now(), num_active_timeouts, remove_timeout_index(), RESUME_INTERRUPTS, schedule_alarm(), SetLatch(), and timeout_params::timeout_handler.

Referenced by InitializeTimeouts().

266 {
267  int save_errno = errno;
268 
269  /*
270  * Bump the holdoff counter, to make sure nothing we call will process
271  * interrupts directly. No timeout handler should do that, but these
272  * failures are hard to debug, so better be sure.
273  */
274  HOLD_INTERRUPTS();
275 
276  /*
277  * SIGALRM is always cause for waking anything waiting on the process
278  * latch.
279  */
280  SetLatch(MyLatch);
281 
282  /*
283  * Fire any pending timeouts, but only if we're enabled to do so.
284  */
285  if (alarm_enabled)
286  {
287  /*
288  * Disable alarms, just in case this platform allows signal handlers
289  * to interrupt themselves. schedule_alarm() will re-enable if
290  * appropriate.
291  */
292  disable_alarm();
293 
294  if (num_active_timeouts > 0)
295  {
297 
298  /* While the first pending timeout has been reached ... */
299  while (num_active_timeouts > 0 &&
300  now >= active_timeouts[0]->fin_time)
301  {
302  timeout_params *this_timeout = active_timeouts[0];
303 
304  /* Remove it from the active list */
306 
307  /* Mark it as fired */
308  this_timeout->indicator = true;
309 
310  /* And call its handler function */
311  this_timeout->timeout_handler();
312 
313  /*
314  * The handler might not take negligible time (CheckDeadLock
315  * for instance isn't too cheap), so let's update our idea of
316  * "now" after each one.
317  */
318  now = GetCurrentTimestamp();
319  }
320 
321  /* Done firing timeouts, so reschedule next interrupt if any */
322  schedule_alarm(now);
323  }
324  }
325 
327 
328  errno = save_errno;
329 }
static void remove_timeout_index(int index)
Definition: timeout.c:124
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:65
timeout_handler_proc timeout_handler
Definition: timeout.c:35
volatile bool indicator
Definition: timeout.c:32
void SetLatch(Latch *latch)
Definition: latch.c:505
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:118
static volatile sig_atomic_t alarm_enabled
Definition: timeout.c:63
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:52
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:116
struct Latch * MyLatch
Definition: globals.c:54
static volatile int num_active_timeouts
Definition: timeout.c:51
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538

◆ InitializeTimeouts()

void InitializeTimeouts ( void  )

Definition at line 346 of file timeout.c.

References timeout_params::active, all_timeouts_initialized, disable_alarm, timeout_params::fin_time, handle_sig_alarm(), i, timeout_params::index, timeout_params::indicator, MAX_TIMEOUTS, num_active_timeouts, pqsignal(), SIGALRM, timeout_params::start_time, and timeout_params::timeout_handler.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackendInitialize(), PostgresMain(), StartBackgroundWorker(), StartupProcessMain(), and WalSndSignals().

347 {
348  int i;
349 
350  /* Initialize, or re-initialize, all local state */
351  disable_alarm();
352 
354 
355  for (i = 0; i < MAX_TIMEOUTS; i++)
356  {
357  all_timeouts[i].index = i;
358  all_timeouts[i].active = false;
359  all_timeouts[i].indicator = false;
362  all_timeouts[i].fin_time = 0;
363  }
364 
366 
367  /* Now establish the signal handler */
369 }
static bool all_timeouts_initialized
Definition: timeout.c:45
TimestampTz fin_time
Definition: timeout.c:38
#define disable_alarm()
Definition: timeout.c:65
timeout_handler_proc timeout_handler
Definition: timeout.c:35
volatile bool indicator
Definition: timeout.c:32
volatile bool active
Definition: timeout.c:31
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
TimestampTz start_time
Definition: timeout.c:37
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:170
TimeoutId index
Definition: timeout.c:28
#define SIGALRM
Definition: win32_port.h:159
int i
static volatile int num_active_timeouts
Definition: timeout.c:51
static void handle_sig_alarm(SIGNAL_ARGS)
Definition: timeout.c:265

◆ insert_timeout()

static void insert_timeout ( TimeoutId  id,
int  index 
)
static

Definition at line 101 of file timeout.c.

References timeout_params::active, Assert, elog, FATAL, i, timeout_params::index, and num_active_timeouts.

Referenced by enable_timeout().

102 {
103  int i;
104 
106  elog(FATAL, "timeout index %d out of range 0..%d", index,
107  num_active_timeouts);
108 
109  Assert(!all_timeouts[id].active);
110  all_timeouts[id].active = true;
111 
112  for (i = num_active_timeouts - 1; i >= index; i--)
113  active_timeouts[i + 1] = active_timeouts[i];
114 
116 
117  num_active_timeouts++;
118 }
volatile bool active
Definition: timeout.c:31
Definition: type.h:89
#define FATAL
Definition: elog.h:52
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
#define Assert(condition)
Definition: c.h:745
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:52
#define elog(elevel,...)
Definition: elog.h:214
int i
static volatile int num_active_timeouts
Definition: timeout.c:51

◆ RegisterTimeout()

TimeoutId RegisterTimeout ( TimeoutId  id,
timeout_handler_proc  handler 
)

Definition at line 380 of file timeout.c.

References all_timeouts_initialized, Assert, ereport, errcode(), errmsg(), FATAL, MAX_TIMEOUTS, timeout_params::timeout_handler, and USER_TIMEOUT.

Referenced by BackendInitialize(), InitPostgres(), and StartupProcessMain().

381 {
383 
384  /* There's no need to disable the signal handler here. */
385 
386  if (id >= USER_TIMEOUT)
387  {
388  /* Allocate a user-defined timeout reason */
389  for (id = USER_TIMEOUT; id < MAX_TIMEOUTS; id++)
390  if (all_timeouts[id].timeout_handler == NULL)
391  break;
392  if (id >= MAX_TIMEOUTS)
393  ereport(FATAL,
394  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
395  errmsg("cannot add more timeout reasons")));
396  }
397 
398  Assert(all_timeouts[id].timeout_handler == NULL);
399 
400  all_timeouts[id].timeout_handler = handler;
401 
402  return id;
403 }
static bool all_timeouts_initialized
Definition: timeout.c:45
int errcode(int sqlerrcode)
Definition: elog.c:610
timeout_handler_proc timeout_handler
Definition: timeout.c:35
#define FATAL
Definition: elog.h:52
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:44
#define ereport(elevel,...)
Definition: elog.h:144
#define Assert(condition)
Definition: c.h:745
int errmsg(const char *fmt,...)
Definition: elog.c:824

◆ remove_timeout_index()

static void remove_timeout_index ( int  index)
static

Definition at line 124 of file timeout.c.

References timeout_params::active, Assert, elog, FATAL, i, timeout_params::index, and num_active_timeouts.

Referenced by disable_timeout(), disable_timeouts(), enable_timeout(), and handle_sig_alarm().

125 {
126  int i;
127 
129  elog(FATAL, "timeout index %d out of range 0..%d", index,
130  num_active_timeouts - 1);
131 
132  Assert(active_timeouts[index]->active);
133  active_timeouts[index]->active = false;
134 
135  for (i = index + 1; i < num_active_timeouts; i++)
136  active_timeouts[i - 1] = active_timeouts[i];
137 
138  num_active_timeouts--;
139 }
volatile bool active
Definition: timeout.c:31
Definition: type.h:89
#define FATAL
Definition: elog.h:52
#define Assert(condition)
Definition: c.h:745
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:52
#define elog(elevel,...)
Definition: elog.h:214
int i
static volatile int num_active_timeouts
Definition: timeout.c:51

◆ reschedule_timeouts()

void reschedule_timeouts ( void  )

Definition at line 415 of file timeout.c.

References all_timeouts_initialized, disable_alarm, GetCurrentTimestamp(), num_active_timeouts, and schedule_alarm().

Referenced by AbortSubTransaction(), and AbortTransaction().

416 {
417  /* For flexibility, allow this to be called before we're initialized. */
419  return;
420 
421  /* Disable timeout interrupts for safety. */
422  disable_alarm();
423 
424  /* Reschedule the interrupt, if any timeouts remain active. */
425  if (num_active_timeouts > 0)
427 }
static bool all_timeouts_initialized
Definition: timeout.c:45
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1574
#define disable_alarm()
Definition: timeout.c:65
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:191
static volatile int num_active_timeouts
Definition: timeout.c:51

◆ schedule_alarm()

static void schedule_alarm ( TimestampTz  now)
static

Definition at line 191 of file timeout.c.

References elog, enable_alarm, FATAL, timeout_params::fin_time, itimerval::it_value, ITIMER_REAL, MemSet, num_active_timeouts, setitimer(), and TimestampDifference().

Referenced by disable_timeout(), disable_timeouts(), enable_timeout_after(), enable_timeout_at(), enable_timeouts(), handle_sig_alarm(), and reschedule_timeouts().

192 {
193  if (num_active_timeouts > 0)
194  {
195  struct itimerval timeval;
196  long secs;
197  int usecs;
198 
199  MemSet(&timeval, 0, sizeof(struct itimerval));
200 
201  /* Get the time remaining till the nearest pending timeout */
203  &secs, &usecs);
204 
205  /*
206  * It's possible that the difference is less than a microsecond;
207  * ensure we don't cancel, rather than set, the interrupt.
208  */
209  if (secs == 0 && usecs == 0)
210  usecs = 1;
211 
212  timeval.it_value.tv_sec = secs;
213  timeval.it_value.tv_usec = usecs;
214 
215  /*
216  * We must enable the signal handler before calling setitimer(); if we
217  * did it in the other order, we'd have a race condition wherein the
218  * interrupt could occur before we can set alarm_enabled, so that the
219  * signal handler would fail to do anything.
220  *
221  * Because we didn't bother to reset the timer in disable_alarm(),
222  * it's possible that a previously-set interrupt will fire between
223  * enable_alarm() and setitimer(). This is safe, however. There are
224  * two possible outcomes:
225  *
226  * 1. The signal handler finds nothing to do (because the nearest
227  * timeout event is still in the future). It will re-set the timer
228  * and return. Then we'll overwrite the timer value with a new one.
229  * This will mean that the timer fires a little later than we
230  * intended, but only by the amount of time it takes for the signal
231  * handler to do nothing useful, which shouldn't be much.
232  *
233  * 2. The signal handler executes and removes one or more timeout
234  * events. When it returns, either the queue is now empty or the
235  * frontmost event is later than the one we looked at above. So we'll
236  * overwrite the timer value with one that is too soon (plus or minus
237  * the signal handler's execution time), causing a useless interrupt
238  * to occur. But the handler will then re-set the timer and
239  * everything will still work as expected.
240  *
241  * Since these cases are of very low probability (the window here
242  * being quite narrow), it's not worth adding cycles to the mainline
243  * code to prevent occasional wasted interrupts.
244  */
245  enable_alarm();
246 
247  /* Set the alarm timer */
248  if (setitimer(ITIMER_REAL, &timeval, NULL) != 0)
249  elog(FATAL, "could not enable SIGALRM timer: %m");
250  }
251 }
#define enable_alarm()
Definition: timeout.c:66
#define MemSet(start, val, len)
Definition: c.h:949
#define FATAL
Definition: elog.h:52
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
Definition: timer.c:86
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:52
#define elog(elevel,...)
Definition: elog.h:214
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1648
static volatile int num_active_timeouts
Definition: timeout.c:51
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538
#define ITIMER_REAL
Definition: win32_port.h:181

Variable Documentation

◆ active_timeouts

timeout_params* volatile active_timeouts[MAX_TIMEOUTS]
static

Definition at line 52 of file timeout.c.

◆ alarm_enabled

volatile sig_atomic_t alarm_enabled = false
static

Definition at line 63 of file timeout.c.

Referenced by handle_sig_alarm().

◆ all_timeouts

timeout_params all_timeouts[MAX_TIMEOUTS]
static

Definition at line 44 of file timeout.c.

◆ all_timeouts_initialized

bool all_timeouts_initialized = false
static

◆ num_active_timeouts