static bool doing_extended_query_message = false;
static bool ignore_till_sync = false;
-/*
- * Flag to keep track of whether statement timeout timer is active.
- */
-static bool stmt_timeout_active = false;
-
/*
* If an unnamed prepared statement exists, it's stored here.
* We keep it separate from the hashtable kept by commands/prepare.c
*/
disable_all_timeouts(false);
QueryCancelPending = false; /* second to avoid race condition */
- stmt_timeout_active = false;
/* Not reading from the client anymore. */
DoingCommandRead = false;
if (StatementTimeout > 0)
{
- if (!stmt_timeout_active)
- {
+ if (!get_timeout_active(STATEMENT_TIMEOUT))
enable_timeout_after(STATEMENT_TIMEOUT, StatementTimeout);
- stmt_timeout_active = true;
- }
}
else
- disable_timeout(STATEMENT_TIMEOUT, false);
+ {
+ if (get_timeout_active(STATEMENT_TIMEOUT))
+ disable_timeout(STATEMENT_TIMEOUT, false);
+ }
}
/*
static void
disable_statement_timeout(void)
{
- if (stmt_timeout_active)
- {
+ if (get_timeout_active(STATEMENT_TIMEOUT))
disable_timeout(STATEMENT_TIMEOUT, false);
-
- stmt_timeout_active = false;
- }
}
{
TimeoutId index; /* identifier of timeout reason */
- /* volatile because it may be changed from the signal handler */
+ /* volatile because these may be changed from the signal handler */
+ volatile bool active; /* true if timeout is in active_timeouts[] */
volatile bool indicator; /* true if timeout has occurred */
/* callback function for timeout, or NULL if timeout not registered */
elog(FATAL, "timeout index %d out of range 0..%d", index,
num_active_timeouts);
+ Assert(!all_timeouts[id].active);
+ all_timeouts[id].active = true;
+
for (i = num_active_timeouts - 1; i >= index; i--)
active_timeouts[i + 1] = active_timeouts[i];
elog(FATAL, "timeout index %d out of range 0..%d", index,
num_active_timeouts - 1);
+ Assert(active_timeouts[index]->active);
+ active_timeouts[index]->active = false;
+
for (i = index + 1; i < num_active_timeouts; i++)
active_timeouts[i - 1] = active_timeouts[i];
* If this timeout was already active, momentarily disable it. We
* interpret the call as a directive to reschedule the timeout.
*/
- i = find_active_timeout(id);
- if (i >= 0)
- remove_timeout_index(i);
+ if (all_timeouts[id].active)
+ remove_timeout_index(find_active_timeout(id));
/*
* Find out the index where to insert the new timeout. We sort by
for (i = 0; i < MAX_TIMEOUTS; i++)
{
all_timeouts[i].index = i;
+ all_timeouts[i].active = false;
all_timeouts[i].indicator = false;
all_timeouts[i].timeout_handler = NULL;
all_timeouts[i].start_time = 0;
void
disable_timeout(TimeoutId id, bool keep_indicator)
{
- int i;
-
/* Assert request is sane */
Assert(all_timeouts_initialized);
Assert(all_timeouts[id].timeout_handler != NULL);
disable_alarm();
/* Find the timeout and remove it from the active list. */
- i = find_active_timeout(id);
- if (i >= 0)
- remove_timeout_index(i);
+ if (all_timeouts[id].active)
+ remove_timeout_index(find_active_timeout(id));
/* Mark it inactive, whether it was active or not. */
if (!keep_indicator)
for (i = 0; i < count; i++)
{
TimeoutId id = timeouts[i].id;
- int idx;
Assert(all_timeouts[id].timeout_handler != NULL);
- idx = find_active_timeout(id);
- if (idx >= 0)
- remove_timeout_index(idx);
+ if (all_timeouts[id].active)
+ remove_timeout_index(find_active_timeout(id));
if (!timeouts[i].keep_indicator)
all_timeouts[id].indicator = false;
void
disable_all_timeouts(bool keep_indicators)
{
+ int i;
+
disable_alarm();
/*
num_active_timeouts = 0;
- if (!keep_indicators)
+ for (i = 0; i < MAX_TIMEOUTS; i++)
{
- int i;
-
- for (i = 0; i < MAX_TIMEOUTS; i++)
+ all_timeouts[i].active = false;
+ if (!keep_indicators)
all_timeouts[i].indicator = false;
}
}
+/*
+ * Return true if the timeout is active (enabled and not yet fired)
+ *
+ * This is, of course, subject to race conditions, as the timeout could fire
+ * immediately after we look.
+ */
+bool
+get_timeout_active(TimeoutId id)
+{
+ return all_timeouts[id].active;
+}
+
/*
* Return the timeout's I've-been-fired indicator
*