Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}
Esempio n. 5
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;
}
Esempio n. 6
0
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);
}
Esempio n. 7
0
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");
    }
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
/*
   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, &timesup);
	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;
}
Esempio n. 11
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;
}
Esempio n. 12
0
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;
}
Esempio n. 13
0
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;
}