/* * Disable SIGALRM and remove all timeouts from the active list, * and optionally reset their timeout indicators. */ void disable_all_timeouts(bool keep_indicators) { disable_alarm(); /* * Only bother to reset the timer if we think it's active. We could just * let the interrupt happen anyway, but it's probably a bit cheaper to do * setitimer() than to let the useless interrupt happen. */ if (num_active_timeouts > 0) { struct itimerval timeval; MemSet(&timeval, 0, sizeof(struct itimerval)); if (setitimer(ITIMER_REAL, &timeval, NULL) != 0) elog(FATAL, "could not disable SIGALRM timer: %m"); } num_active_timeouts = 0; if (!keep_indicators) { int i; for (i = 0; i < MAX_TIMEOUTS; i++) all_timeouts[i].indicator = false; } }
/* * Cancel the specified timeout. * * The timeout's I've-been-fired indicator is reset, * unless keep_indicator is true. * * When a timeout is canceled, any other active timeout remains in force. * It's not an error to disable a timeout that is not enabled. */ 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 timeout interrupts for safety. */ disable_alarm(); /* Find the timeout and remove it from the active list. */ i = find_active_timeout(id); if (i >= 0) remove_timeout_index(i); /* Mark it inactive, whether it was active or not. */ if (!keep_indicator) all_timeouts[id].indicator = false; /* Reschedule the interrupt, if any timeouts remain active. */ if (num_active_timeouts > 0) schedule_alarm(GetCurrentTimestamp()); }
void gui_Next(void) { if ( gui_menu.me_list == melist_active_alarm_menu ) { disable_alarm(); if ( gui_alarm_list[gui_data.active_alarm_idx].snooze_count != 0 ) { int i; /* this is already the snooze alarm, so clear all and behave like the normal alarm off */ for( i = 0; i < GUI_ALARM_CNT; i++ ) gui_alarm_list[i].snooze_count = 0; } else { /* enable snooze */ gui_alarm_list[gui_data.active_alarm_idx].snooze_count = 1; } gui_data.is_alarm = 0; gui_Recalculate(); menu_SetMEList(&gui_menu, melist_display_time, 0); } else { menu_NextFocus(&gui_menu); } }
/* * Cancel multiple timeouts at once. * * The timeouts' I've-been-fired indicators are reset, * unless timeouts[i].keep_indicator is true. * * This works like calling disable_timeout() multiple times. * Use this to reduce the number of GetCurrentTimestamp() * and setitimer() calls needed to cancel multiple timeouts. */ void disable_timeouts(const DisableTimeoutParams *timeouts, int count) { int i; Assert(all_timeouts_initialized); /* Disable timeout interrupts for safety. */ disable_alarm(); /* Cancel the timeout(s). */ 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 (!timeouts[i].keep_indicator) all_timeouts[id].indicator = false; } /* Reschedule the interrupt, if any timeouts remain active. */ if (num_active_timeouts > 0) schedule_alarm(GetCurrentTimestamp()); }
int stream_handler::on_parse_complete(inmessage* msg) { if (state_ == CONNECT) { state_ = REQUEST; disable_alarm(); } return msghandler_->on_message(this, msg); }
stream_handler::~stream_handler(void) { disable_alarm(); if (msgparser_ != NULL) { delete msgparser_; msgparser_ = NULL; } }
/* * Reschedule any pending SIGALRM interrupt. * * This can be used during error recovery in case query cancel resulted in loss * of a SIGALRM event (due to longjmp'ing out of handle_sig_alarm before it * could do anything). But note it's not necessary if any of the public * enable_ or disable_timeout functions are called in the same area, since * those all do schedule_alarm() internally if needed. */ void reschedule_timeouts(void) { /* For flexibility, allow this to be called before we're initialized. */ if (!all_timeouts_initialized) return; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Reschedule the interrupt, if any timeouts remain active. */ if (num_active_timeouts > 0) schedule_alarm(GetCurrentTimestamp()); }
/* * Enable the specified timeout to fire at the specified time. * * This is provided to support cases where there's a reason to calculate * the timeout by reference to some point other than "now". If there isn't, * use enable_timeout_after(), to avoid calling GetCurrentTimestamp() twice. */ void enable_timeout_at(TimeoutId id, TimestampTz fin_time) { TimestampTz now; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Queue the timeout at the appropriate time. */ now = GetCurrentTimestamp(); enable_timeout(id, now, fin_time); /* Set the timer interrupt. */ schedule_alarm(now); }
/* * Enable the specified timeout to fire after the specified delay. * * Delay is given in milliseconds. */ void enable_timeout_after(TimeoutId id, int delay_ms) { TimestampTz now; TimestampTz fin_time; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Queue the timeout at the appropriate time. */ now = GetCurrentTimestamp(); fin_time = TimestampTzPlusMilliseconds(now, delay_ms); enable_timeout(id, now, fin_time); /* Set the timer interrupt. */ schedule_alarm(now); }
void gui_Select(void) { if ( gui_menu.me_list == melist_active_alarm_menu ) { int i; disable_alarm(); for( i = 0; i < GUI_ALARM_CNT; i++ ) gui_alarm_list[i].snooze_count = 0; gui_data.is_alarm = 0; gui_Recalculate(); menu_SetMEList(&gui_menu, melist_display_time, 0); } else { menu_Select(&gui_menu); } }
int main (int argc, char **argv) { (void) argc; (void) argv; int exc = 0; do_exception (&exc); if ( ! exc ) { set_alarm (1); //failed (); sleep (10); } else { if ( exc == timeout_ex ) { printf ("timeout!\n"); } else if ( exc ) { printf ("error code: %d\n", exc); } } disable_alarm (); return EXIT_SUCCESS; }
/* * Enable multiple timeouts at once. * * This works like calling enable_timeout_after() and/or enable_timeout_at() * multiple times. Use this to reduce the number of GetCurrentTimestamp() * and setitimer() calls needed to establish multiple timeouts. */ void enable_timeouts(const EnableTimeoutParams *timeouts, int count) { TimestampTz now; int i; /* Disable timeout interrupts for safety. */ disable_alarm(); /* Queue the timeout(s) at the appropriate times. */ now = GetCurrentTimestamp(); for (i = 0; i < count; i++) { TimeoutId id = timeouts[i].id; TimestampTz fin_time; switch (timeouts[i].type) { case TMPARAM_AFTER: fin_time = TimestampTzPlusMilliseconds(now, timeouts[i].delay_ms); enable_timeout(id, now, fin_time); break; case TMPARAM_AT: enable_timeout(id, now, timeouts[i].fin_time); break; default: elog(ERROR, "unrecognized timeout type %d", (int) timeouts[i].type); break; } } /* Set the timer interrupt. */ schedule_alarm(now); }
/* * Initialize timeout module. * * This must be called in every process that wants to use timeouts. * * If the process was forked from another one that was also using this * module, be sure to call this before re-enabling signals; else handlers * meant to run in the parent process might get invoked in this one. */ void InitializeTimeouts(void) { int i; /* Initialize, or re-initialize, all local state */ disable_alarm(); num_active_timeouts = 0; for (i = 0; i < MAX_TIMEOUTS; i++) { all_timeouts[i].index = i; all_timeouts[i].indicator = false; all_timeouts[i].timeout_handler = NULL; all_timeouts[i].start_time = 0; all_timeouts[i].fin_time = 0; } all_timeouts_initialized = true; /* Now establish the signal handler */ pqsignal(SIGALRM, handle_sig_alarm); }
/* * Signal handler for SIGALRM * * Process any active timeout reasons and then reschedule the interrupt * as needed. */ static void handle_sig_alarm(SIGNAL_ARGS) { int save_errno = errno; bool save_ImmediateInterruptOK = ImmediateInterruptOK; /* * We may be executing while ImmediateInterruptOK is true (e.g., when * mainline is waiting for a lock). If SIGINT or similar arrives while * this code is running, we'd lose control and perhaps leave our data * structures in an inconsistent state. Disable immediate interrupts, and * just to be real sure, bump the holdoff counter as well. (The reason * for this belt-and-suspenders-too approach is to make sure that nothing * bad happens if a timeout handler calls code that manipulates * ImmediateInterruptOK.) * * Note: it's possible for a SIGINT to interrupt handle_sig_alarm before * we manage to do this; the net effect would be as if the SIGALRM event * had been silently lost. Therefore error recovery must include some * action that will allow any lost interrupt to be rescheduled. Disabling * some or all timeouts is sufficient, or if that's not appropriate, * reschedule_timeouts() can be called. Also, the signal blocking hazard * described below applies here too. */ ImmediateInterruptOK = false; HOLD_INTERRUPTS(); /* * SIGALRM is always cause for waking anything waiting on the process * latch. Cope with MyProc not being there, as the startup process also * uses this signal handler. */ if (MyProc) SetLatch(&MyProc->procLatch); /* * Fire any pending timeouts, but only if we're enabled to do so. */ if (alarm_enabled) { /* * Disable alarms, just in case this platform allows signal handlers * to interrupt themselves. schedule_alarm() will re-enable if * appropriate. */ disable_alarm(); if (num_active_timeouts > 0) { TimestampTz now = GetCurrentTimestamp(); /* While the first pending timeout has been reached ... */ while (num_active_timeouts > 0 && now >= active_timeouts[0]->fin_time) { timeout_params *this_timeout = active_timeouts[0]; /* Remove it from the active list */ remove_timeout_index(0); /* Mark it as fired */ this_timeout->indicator = true; /* And call its handler function */ (*this_timeout->timeout_handler) (); /* * The handler might not take negligible time (CheckDeadLock * for instance isn't too cheap), so let's update our idea of * "now" after each one. */ now = GetCurrentTimestamp(); } /* Done firing timeouts, so reschedule next interrupt if any */ schedule_alarm(now); } } /* * Re-allow query cancel, and then try to service any cancel request that * arrived meanwhile (this might in particular include a cancel request * fired by one of the timeout handlers). Since we are in a signal * handler, we mustn't call ProcessInterrupts unless ImmediateInterruptOK * is set; if it isn't, the cancel will happen at the next mainline * CHECK_FOR_INTERRUPTS. * * Note: a longjmp from here is safe so far as our own data structures are * concerned; but on platforms that block a signal before calling the * handler and then un-block it on return, longjmping out of the signal * handler leaves SIGALRM still blocked. Error cleanup is responsible for * unblocking any blocked signals. */ RESUME_INTERRUPTS(); ImmediateInterruptOK = save_ImmediateInterruptOK; if (save_ImmediateInterruptOK) CHECK_FOR_INTERRUPTS(); errno = save_errno; }
/* * Signal handler for SIGALRM * * Process any active timeout reasons and then reschedule the interrupt * as needed. */ static void handle_sig_alarm(SIGNAL_ARGS) { int save_errno = errno; /* * Bump the holdoff counter, to make sure nothing we call will process * interrupts directly. No timeout handler should do that, but these * failures are hard to debug, so better be sure. */ HOLD_INTERRUPTS(); /* * SIGALRM is always cause for waking anything waiting on the process * latch. */ SetLatch(MyLatch); /* * Fire any pending timeouts, but only if we're enabled to do so. */ if (alarm_enabled) { /* * Disable alarms, just in case this platform allows signal handlers * to interrupt themselves. schedule_alarm() will re-enable if * appropriate. */ disable_alarm(); if (num_active_timeouts > 0) { TimestampTz now = GetCurrentTimestamp(); /* While the first pending timeout has been reached ... */ while (num_active_timeouts > 0 && now >= active_timeouts[0]->fin_time) { timeout_params *this_timeout = active_timeouts[0]; /* Remove it from the active list */ remove_timeout_index(0); /* Mark it as fired */ this_timeout->indicator = true; /* And call its handler function */ (*this_timeout->timeout_handler) (); /* * The handler might not take negligible time (CheckDeadLock * for instance isn't too cheap), so let's update our idea of * "now" after each one. */ now = GetCurrentTimestamp(); } /* Done firing timeouts, so reschedule next interrupt if any */ schedule_alarm(now); } } RESUME_INTERRUPTS(); errno = save_errno; }