|
|
|
@ -27,10 +27,12 @@
|
|
|
|
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include "timer.hh"
|
|
|
|
|
#include "lnav_log.hh"
|
|
|
|
|
|
|
|
|
|
const struct itimerval disable = {
|
|
|
|
|
static const struct itimerval DISABLE_TV = {
|
|
|
|
|
{ 0, 0 },
|
|
|
|
|
{ 0, 0 }
|
|
|
|
|
};
|
|
|
|
@ -39,20 +41,25 @@ timer::error::error(int err):e_err(err) { }
|
|
|
|
|
|
|
|
|
|
timer::interrupt_timer::interrupt_timer(struct timeval t,
|
|
|
|
|
sighandler_t_ sighandler=SIG_IGN) : new_handler(sighandler),
|
|
|
|
|
old_handler(NULL), new_val((struct itimerval){{0,0},t}),
|
|
|
|
|
old_val(disable), armed(false) { }
|
|
|
|
|
new_val((struct itimerval){{0,0},t}),
|
|
|
|
|
old_val(DISABLE_TV), armed(false) {
|
|
|
|
|
memset(&this->old_handler, 0, sizeof(this->old_handler));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int timer::interrupt_timer::arm_timer() {
|
|
|
|
|
struct sigaction sa;
|
|
|
|
|
|
|
|
|
|
// Disable the interval timer before setting the handler and arming the
|
|
|
|
|
// interval timer or else we will have a race-condition where the timer
|
|
|
|
|
// might fire and the appropriate handler might not be set.
|
|
|
|
|
if (setitimer(ITIMER_REAL, &disable, &this->old_val) != 0) {
|
|
|
|
|
if (setitimer(ITIMER_REAL, &DISABLE_TV, &this->old_val) != 0) {
|
|
|
|
|
log_error("Unable to disable the timer: %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
this->old_handler = signal(SIGALRM, this->new_handler);
|
|
|
|
|
if (this->old_handler == SIG_ERR) {
|
|
|
|
|
memset(&sa, 0, sizeof(sa));
|
|
|
|
|
sa.sa_handler = this->new_handler;
|
|
|
|
|
if (sigaction(SIGALRM, &sa, &this->old_handler) == -1) {
|
|
|
|
|
log_error("Unable to set the signal handler: %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
if (setitimer(ITIMER_REAL, &this->old_val, NULL) != 0) {
|
|
|
|
@ -64,7 +71,7 @@ int timer::interrupt_timer::arm_timer() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (setitimer(ITIMER_REAL, &this->new_val, NULL) != 0) {
|
|
|
|
|
if(signal(SIGALRM, this->old_handler) == SIG_ERR) {
|
|
|
|
|
if(sigaction(SIGALRM, &this->old_handler, NULL) == -1) {
|
|
|
|
|
log_error("Unable to reset the signal handler: %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
throw timer::error(errno);
|
|
|
|
@ -86,12 +93,12 @@ void timer::interrupt_timer::disarm_timer() {
|
|
|
|
|
// the previous interval timer or else we will have a race-condition
|
|
|
|
|
// where the timer might fire and the appropriate handler might not be
|
|
|
|
|
// set.
|
|
|
|
|
if (setitimer(ITIMER_REAL, &disable, NULL) != 0) {
|
|
|
|
|
if (setitimer(ITIMER_REAL, &DISABLE_TV, NULL) != 0) {
|
|
|
|
|
log_error("Failed to disable the timer: %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
throw timer::error(errno);
|
|
|
|
|
}
|
|
|
|
|
if (signal(SIGALRM, this->old_handler) == SIG_ERR) {
|
|
|
|
|
if (sigaction(SIGALRM, &this->old_handler, NULL) == -1) {
|
|
|
|
|
log_error("Failed to reinstall previous SIGALRM handler: %s",
|
|
|
|
|
strerror(errno));
|
|
|
|
|
throw timer::error(errno);
|
|
|
|
@ -102,8 +109,8 @@ void timer::interrupt_timer::disarm_timer() {
|
|
|
|
|
throw timer::error(errno);
|
|
|
|
|
}
|
|
|
|
|
this->armed = false;
|
|
|
|
|
this->old_val = disable;
|
|
|
|
|
this->old_handler = NULL;
|
|
|
|
|
this->old_val = DISABLE_TV;
|
|
|
|
|
memset(&this->old_handler, 0, sizeof(this->old_handler));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|