static void ldap_id_enumerate_timer(struct tevent_context *ev, struct tevent_timer *tt, struct timeval tv, void *pvt) { struct sdap_id_ctx *ctx = talloc_get_type(pvt, struct sdap_id_ctx); struct tevent_timer *timeout; struct tevent_req *req; int delay; errno_t ret; if (be_is_offline(ctx->be)) { DEBUG(4, ("Backend is marked offline, retry later!\n")); /* schedule starting from now, not the last run */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); ldap_id_enumerate_set_timer(ctx, tv); return; } req = ldap_id_enumerate_send(ev, ctx); if (!req) { DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); /* schedule starting from now, not the last run */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); ret = ldap_id_enumerate_set_timer(ctx, tv); if (ret != EOK) { DEBUG(1, ("Error setting up enumerate timer\n")); } return; } tevent_req_set_callback(req, ldap_id_enumerate_reschedule, ctx); /* if enumeration takes so long, either we try to enumerate too * frequently, or something went seriously wrong */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); timeout = tevent_add_timer(ctx->be->ev, req, tv, ldap_id_enumerate_timeout, req); if (timeout == NULL) { /* If we can't guarantee a timeout, we * need to cancel the request, to avoid * the possibility of starting another * concurrently */ talloc_zfree(req); DEBUG(1, ("Failed to schedule enumeration, retrying later!\n")); /* schedule starting from now, not the last run */ delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); tv = tevent_timeval_current_ofs(delay, 0); ret = ldap_id_enumerate_set_timer(ctx, tv); if (ret != EOK) { DEBUG(1, ("Error setting up enumerate timer\n")); } return; } return; }
static int sdap_sudo_schedule_smart_refresh(struct sdap_sudo_ctx *sudo_ctx, time_t delay) { struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; struct tevent_req *req = NULL; struct timeval tv; /* schedule new refresh */ tv = tevent_timeval_current_ofs(delay, 0); req = sdap_sudo_timer_send(sudo_ctx, id_ctx->be->ev, sudo_ctx, tv, delay, sdap_sudo_smart_refresh_send); if (req == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule smart refresh of sudo " "rules!\n")); return ENOMEM; } tevent_req_set_callback(req, sdap_sudo_periodical_smart_refresh_done, sudo_ctx); DEBUG(SSSDBG_TRACE_FUNC, ("Smart refresh scheduled at: %lld\n", (long long)tv.tv_sec)); return EOK; }
void switch_sigint_enabled(struct tevent_context *ev, struct tevent_timer *te, struct timeval t, void *private_data) { struct timeval tv; struct tevent_timer *event_timer = NULL; struct main_context *main_ctx = talloc_get_type(private_data, struct main_context); if (main_ctx->is_sigint_enabled) { main_ctx->is_sigint_enabled = 0; DEBUG("SIGINT disabled"); } else { main_ctx->is_sigint_enabled = 1; DEBUG("SIGINT enabled"); } tv = tevent_timeval_current_ofs(SIGINT_SWITCH_TIMEOUT, 0); event_timer = tevent_add_timer(main_ctx->event_ctx, main_ctx->event_ctx, tv, switch_sigint_enabled, main_ctx); if (event_timer == NULL) { DEBUG("tevent_add_signal() failed"); } }
static void ctdb_mutex_rados_timer_cb(struct tevent_context *ev, struct tevent_timer *te, struct timeval current_time, void *private_data) { struct ctdb_mutex_rados_state *cmr_state = private_data; int ret; if (!cmr_state->holding_mutex) { fprintf(stderr, "Timer callback invoked without mutex!\n"); ret = -EINVAL; goto err_ctx_cleanup; } if ((kill(cmr_state->ppid, 0) == 0) || (errno != ESRCH)) { /* parent still around, keep waiting */ cmr_state->timer_ev = tevent_add_timer(cmr_state->ev, cmr_state, tevent_timeval_current_ofs(5, 0), ctdb_mutex_rados_timer_cb, cmr_state); if (cmr_state->timer_ev == NULL) { fprintf(stderr, "Failed to create timer event\n"); /* rely on signal cb */ } return; } /* parent ended, drop lock and exit */ ret = ctdb_mutex_rados_unlock(cmr_state->ioctx, cmr_state->object); err_ctx_cleanup: ctdb_mutex_rados_ctx_destroy(cmr_state->ceph_cluster, cmr_state->ioctx); talloc_free(cmr_state); exit(ret ? 1 : 0); }
static int sdap_sudo_schedule_refresh(TALLOC_CTX *mem_ctx, struct sdap_sudo_ctx *sudo_ctx, enum sdap_sudo_refresh_type refresh, tevent_req_fn callback, time_t delay, time_t timeout, struct tevent_req **_req) { struct tevent_req *req = NULL; sdap_sudo_timer_fn_t send_fn = NULL; const char *name = NULL; struct timeval when; when = tevent_timeval_current_ofs(delay, 0); switch (refresh) { case SDAP_SUDO_REFRESH_FULL: send_fn = sdap_sudo_full_refresh_send; name = "Full refresh"; break; case SDAP_SUDO_REFRESH_SMART: send_fn = sdap_sudo_smart_refresh_send; name = "Smart refresh"; break; case SDAP_SUDO_REFRESH_RULES: DEBUG(SSSDBG_OP_FAILURE, "Rules refresh can't be scheduled!\n"); return EINVAL; default: DEBUG(SSSDBG_CRIT_FAILURE, "Unknown refresh type [%d].\n", refresh); return EINVAL; } req = sdap_sudo_timer_send(mem_ctx, sudo_ctx->id_ctx->be->ev, sudo_ctx, when, timeout, send_fn); if (req == NULL) { return ENOMEM; } tevent_req_set_callback(req, callback, sudo_ctx); DEBUG(SSSDBG_TRACE_FUNC, "%s scheduled at: %lld\n", name, (long long)when.tv_sec); if (_req != NULL) { *_req = req; } return EOK; }
static void ldap_id_enumerate_timeout(struct tevent_context *ev, struct tevent_timer *te, struct timeval tv, void *pvt) { struct tevent_req *req = talloc_get_type(pvt, struct tevent_req); struct sdap_id_ctx *ctx = tevent_req_callback_data(req, struct sdap_id_ctx); int delay; delay = dp_opt_get_int(ctx->opts->basic, SDAP_ENUM_REFRESH_TIMEOUT); DEBUG(1, ("Enumeration timed out! Timeout too small? (%ds)!\n", delay)); tv = tevent_timeval_current_ofs(delay, 0); ldap_id_enumerate_set_timer(ctx, tv); talloc_zfree(req); }
static void watchdog_event_handler(struct tevent_context *ev, struct tevent_timer *te, struct timeval current_time, void *private_data) { /* first thing reset the watchdog ticks */ watchdog_reset(); /* then set a new watchodg event */ watchdog_ctx.te = tevent_add_timer(ev, ev, tevent_timeval_current_ofs(watchdog_ctx.interval.tv_sec, 0), watchdog_event_handler, NULL); /* if the function fails the watchdog will kill the * process soon enough, so we just warn */ if (!watchdog_ctx.te) { DEBUG(SSSDBG_FATAL_FAILURE, "Failed to create a watchdog timer event!\n"); } }
errno_t setup_event_handlers(struct main_context *main_ctx, struct tevent_context *event_ctx) { struct tevent_signal *event_signal = NULL; struct tevent_timer *event_timer = NULL; struct timeval tv; event_signal = tevent_add_signal(event_ctx, event_ctx, SIGINT, 0, on_sigint, main_ctx); if (event_signal == NULL) { DEBUG("tevent_add_signal() failed"); return EIO; } tv = tevent_timeval_current_ofs(SIGINT_SWITCH_TIMEOUT, 0); event_timer = tevent_add_timer(event_ctx, event_ctx, tv, switch_sigint_enabled, main_ctx); if (event_timer == NULL) { DEBUG("tevent_add_signal() failed"); return EIO; } return EOK; }
/* Wait a short period of time to receive a single oplock break request */ static void torture_wait_for_lease_break(struct torture_context *tctx) { TALLOC_CTX *tmp_ctx = talloc_new(NULL); struct tevent_timer *te = NULL; struct timeval ne; bool timesup = false; int old_count = break_info.count; /* Wait .1 seconds for an lease break */ ne = tevent_timeval_current_ofs(0, 100000); te = tevent_add_timer(tctx->ev, tmp_ctx, ne, timeout_cb, ×up); if (te == NULL) { torture_comment(tctx, "Failed to wait for an oplock break. " "test results may not be accurate."); goto done; } while (!timesup && break_info.count < old_count + 1) { if (tevent_loop_once(tctx->ev) != 0) { torture_comment(tctx, "Failed to wait for an oplock " "break. test results may not be " "accurate."); goto done; } } done: /* We don't know if the timed event fired and was freed, we received * our oplock break, or some other event triggered the loop. Thus, * we create a tmp_ctx to be able to safely free/remove the timed * event in all 3 cases. */ talloc_free(tmp_ctx); return; }
int main(int argc, char *argv[]) { int ret; struct ctdb_mutex_rados_state *cmr_state; progname = argv[0]; if (argc != 5) { fprintf(stderr, "Usage: %s <Ceph Cluster> <Ceph user> " "<RADOS pool> <RADOS object>\n", progname); ret = -EINVAL; goto err_out; } ret = setvbuf(stdout, NULL, _IONBF, 0); if (ret != 0) { fprintf(stderr, "Failed to configure unbuffered stdout I/O\n"); } cmr_state = talloc_zero(NULL, struct ctdb_mutex_rados_state); if (cmr_state == NULL) { fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; goto err_out; } cmr_state->ceph_cluster_name = argv[1]; cmr_state->ceph_auth_name = argv[2]; cmr_state->pool_name = argv[3]; cmr_state->object = argv[4]; cmr_state->ppid = getppid(); if (cmr_state->ppid == 1) { /* * The original parent is gone and the process has * been reparented to init. This can happen if the * helper is started just as the parent is killed * during shutdown. The error message doesn't need to * be stellar, since there won't be anything around to * capture and log it... */ fprintf(stderr, "%s: PPID == 1\n", progname); ret = -EPIPE; goto err_state_free; } cmr_state->ev = tevent_context_init(cmr_state); if (cmr_state->ev == NULL) { fprintf(stderr, "tevent_context_init failed\n"); fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; goto err_state_free; } /* wait for sigterm */ cmr_state->sig_ev = tevent_add_signal(cmr_state->ev, cmr_state, SIGTERM, 0, ctdb_mutex_rados_sigterm_cb, cmr_state); if (cmr_state->sig_ev == NULL) { fprintf(stderr, "Failed to create signal event\n"); fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; goto err_state_free; } /* periodically check parent */ cmr_state->timer_ev = tevent_add_timer(cmr_state->ev, cmr_state, tevent_timeval_current_ofs(5, 0), ctdb_mutex_rados_timer_cb, cmr_state); if (cmr_state->timer_ev == NULL) { fprintf(stderr, "Failed to create timer event\n"); fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); ret = -ENOMEM; goto err_state_free; } ret = ctdb_mutex_rados_ctx_create(cmr_state->ceph_cluster_name, cmr_state->ceph_auth_name, cmr_state->pool_name, &cmr_state->ceph_cluster, &cmr_state->ioctx); if (ret < 0) { fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); goto err_state_free; } ret = ctdb_mutex_rados_lock(cmr_state->ioctx, cmr_state->object); if ((ret == -EEXIST) || (ret == -EBUSY)) { fprintf(stdout, CTDB_MUTEX_STATUS_CONTENDED); goto err_ctx_cleanup; } else if (ret < 0) { fprintf(stdout, CTDB_MUTEX_STATUS_ERROR); goto err_ctx_cleanup; } cmr_state->holding_mutex = true; fprintf(stdout, CTDB_MUTEX_STATUS_HOLDING); /* wait for the signal / timer events to do their work */ ret = tevent_loop_wait(cmr_state->ev); if (ret < 0) { goto err_ctx_cleanup; } err_ctx_cleanup: ctdb_mutex_rados_ctx_destroy(cmr_state->ceph_cluster, cmr_state->ioctx); err_state_free: talloc_free(cmr_state); err_out: return ret ? 1 : 0; }
static int sdap_sudo_setup_periodical_refresh(struct sdap_sudo_ctx *sudo_ctx) { struct sdap_id_ctx *id_ctx = sudo_ctx->id_ctx; struct tevent_req *req; time_t smart_default; time_t smart_interval; time_t full_interval; time_t last_full; struct timeval tv; int ret; smart_interval = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL); full_interval = dp_opt_get_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL); if (smart_interval == 0 && full_interval == 0) { smart_default = id_ctx->opts->basic[SDAP_SUDO_SMART_REFRESH_INTERVAL].def_val.number; DEBUG(SSSDBG_MINOR_FAILURE, ("At least one periodical update has to be " "enabled. Setting smart refresh interval to default value (%d).\n", smart_default)); ret = dp_opt_set_int(id_ctx->opts->basic, SDAP_SUDO_SMART_REFRESH_INTERVAL, smart_default); if (ret != EOK) { return ret; } } if (full_interval <= smart_interval) { DEBUG(SSSDBG_MINOR_FAILURE, ("Full refresh interval has to be greater" "than smart refresh interval. Periodical full refresh will be " "disabled.\n")); ret = dp_opt_set_int(id_ctx->opts->basic, SDAP_SUDO_FULL_REFRESH_INTERVAL, 0); if (ret != EOK) { return ret; } } ret = sysdb_sudo_get_last_full_refresh(id_ctx->be->sysdb, &last_full); if (ret != EOK) { return ret; } if (last_full == 0) { /* If this is the first startup, we need to kick off * an refresh immediately, to close a window where * clients requesting sudo information won't get an * immediate reply with no entries */ tv = tevent_timeval_current(); } else { /* At least one update has previously run, * so clients will get cached data. * We will delay the refresh so we don't slow * down the startup process if this is happening * during system boot. */ /* delay at least by 10s */ tv = tevent_timeval_current_ofs(10, 0); } req = sdap_sudo_timer_send(sudo_ctx, id_ctx->be->ev, sudo_ctx, tv, full_interval, sdap_sudo_full_refresh_send); if (req == NULL) { DEBUG(SSSDBG_OP_FAILURE, ("Unable to schedule full refresh of sudo " "rules! Periodical updates will not work!\n")); return ENOMEM; } tevent_req_set_callback(req, sdap_sudo_periodical_first_refresh_done, sudo_ctx); DEBUG(SSSDBG_TRACE_FUNC, ("Full refresh scheduled at: %lld\n", (long long)tv.tv_sec)); return EOK; }
static void be_ptask_schedule(struct be_ptask *task, enum be_ptask_delay delay_type, enum be_ptask_schedule from) { struct timeval tv; time_t delay = 0; if (!task->enabled) { DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: disabled\n", task->name); return; } switch (delay_type) { case BE_PTASK_FIRST_DELAY: delay = task->first_delay; break; case BE_PTASK_ENABLED_DELAY: delay = task->enabled_delay; break; case BE_PTASK_PERIOD: delay = task->period; if (backoff_allowed(task) && task->period * 2 <= task->max_backoff) { /* double the period for the next execution */ task->period *= 2; } break; } /* add random offset */ if (task->random_offset != 0) { delay = delay + (rand_r(&task->ro_seed) % task->random_offset); } switch (from) { case BE_PTASK_SCHEDULE_FROM_NOW: tv = tevent_timeval_current_ofs(delay, 0); DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: scheduling task %lu seconds " "from now [%lu]\n", task->name, delay, tv.tv_sec); break; case BE_PTASK_SCHEDULE_FROM_LAST: tv = tevent_timeval_set(task->last_execution + delay, 0); DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: scheduling task %lu seconds " "from last execution time [%lu]\n", task->name, delay, tv.tv_sec); break; } if (task->timer != NULL) { DEBUG(SSSDBG_MINOR_FAILURE, "Task [%s]: another timer is already " "active?\n", task->name); talloc_zfree(task->timer); } task->timer = tevent_add_timer(task->ev, task, tv, be_ptask_execute, task); if (task->timer == NULL) { /* nothing we can do about it */ DEBUG(SSSDBG_CRIT_FAILURE, "FATAL: Unable to schedule task [%s]\n", task->name); be_ptask_disable(task); } task->next_execution = tv.tv_sec; }
static void be_ptask_execute(struct tevent_context *ev, struct tevent_timer *tt, struct timeval tv, void *pvt) { struct be_ptask *task = NULL; struct tevent_timer *timeout = NULL; task = talloc_get_type(pvt, struct be_ptask); task->timer = NULL; /* timer is freed by tevent */ if (be_is_offline(task->be_ctx)) { DEBUG(SSSDBG_TRACE_FUNC, "Back end is offline\n"); switch (task->offline) { case BE_PTASK_OFFLINE_SKIP: be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW); return; case BE_PTASK_OFFLINE_DISABLE: /* This case is normally handled by offline callback but we * should handle it here as well since we can get here in some * special cases for example unit tests or tevent events order. */ be_ptask_disable(task); return; case BE_PTASK_OFFLINE_EXECUTE: /* continue */ break; } } DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: executing task, timeout %lu " "seconds\n", task->name, task->timeout); task->last_execution = tv.tv_sec; task->req = task->send_fn(task, task->ev, task->be_ctx, task, task->pvt); if (task->req == NULL) { /* skip this iteration and try again later */ DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed to execute task, " "will try again later\n", task->name); be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW); return; } tevent_req_set_callback(task->req, be_ptask_done, task); /* schedule timeout */ if (task->timeout > 0) { tv = tevent_timeval_current_ofs(task->timeout, 0); timeout = tevent_add_timer(task->ev, task->req, tv, be_ptask_timeout, task); if (timeout == NULL) { /* If we can't guarantee a timeout, * we need to cancel the request. */ talloc_zfree(task->req); DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed to set timeout, " "the task will be rescheduled\n", task->name); be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW); } } return; }