diff options
| author | Fabiano Fidêncio <fidencio@redhat.com> | 2016-11-22 15:02:33 +0100 |
|---|---|---|
| committer | Lukas Slebodnik <lslebodn@redhat.com> | 2017-01-23 18:46:37 +0100 |
| commit | 151a6de4793e0045a7085d4d72b975947662e566 (patch) | |
| tree | 5082d9cb1c9b40ca9148672865c59fefa36cad75 /src/responder/common | |
| parent | 32c76642250b3ba3b173d0576c0d00b0190320a9 (diff) | |
| download | sssd-151a6de4793e0045a7085d4d72b975947662e566.tar.gz sssd-151a6de4793e0045a7085d4d72b975947662e566.tar.xz sssd-151a6de4793e0045a7085d4d72b975947662e566.zip | |
RESPONDER: Shutdown {dbus,socket}-activated responders in case they're idle
This commit introduces a new option for the responders called
responder_idle_timeout, which specifies the number of seconds that the
responder process can be up without being used. The default value is
300 seconds (5 minutes) and can be configured per responder, being 60
seconds the minimum acceptable value.
Is important to note that setting "responder_idle_timeout = 0" disables
the responder timeout, which makes sense for the responders that always
will be running.
The shutdown timeout is activated per responder in case the responder
has been {dbus,socket}-activated. In case of any commnunication with the
responder the timeout is reset thereby ensuring we won't shutdown a
responder that is not idle.
Setting the responder's last request time is done slightly differently
for socket-activated and dbus-activated responders. In both cases it's
updated in any internal communication in sbus_message_handler(), but
for the socket-activated responders it's also updated when the
responder's socket is used.
Currently it works properly with all responders but the secrets one,
which has a different logic and must be treated separately in case some
change is required there.
Is worth to mention that this commit does not affect the responders
explicitly configured in the "services" line of sssd.conf.
Related:
https://fedorahosted.org/sssd/ticket/3245
Signed-off-by: Fabiano Fidêncio <fidencio@redhat.com>
Reviewed-by: Pavel Březina <pbrezina@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Diffstat (limited to 'src/responder/common')
| -rw-r--r-- | src/responder/common/responder.h | 4 | ||||
| -rw-r--r-- | src/responder/common/responder_common.c | 129 |
2 files changed, 132 insertions, 1 deletions
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h index 860b55fc9..9c8b5f942 100644 --- a/src/responder/common/responder.h +++ b/src/responder/common/responder.h @@ -108,6 +108,10 @@ struct resp_ctx { int domains_timeout; int client_idle_timeout; + time_t last_request_time; + int idle_timeout; + struct tevent_timer *idle; + struct sss_cmd_table *sss_cmds; const char *sss_pipe_name; const char *confdb_service_path; diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c index e4b0b7e9f..d46571d2b 100644 --- a/src/responder/common/responder_common.c +++ b/src/responder/common/responder_common.c @@ -350,6 +350,88 @@ static void client_recv(struct cli_ctx *cctx) return; } +static errno_t schedule_responder_idle_timer(struct resp_ctx *rctx); + +static void responder_idle_handler(struct tevent_context *ev, + struct tevent_timer *te, + struct timeval current_time, + void *data) +{ + struct resp_ctx *rctx; + time_t now; + + rctx = talloc_get_type(data, struct resp_ctx); + + now = time(NULL); + if (rctx->last_request_time > now) { + DEBUG(SSSDBG_IMPORTANT_INFO, + "Time shift detected, re-scheduling the responder timeout\n"); + goto end; + } + + if ((now - rctx->last_request_time) > rctx->idle_timeout) { + /* This responder is idle. Terminate it */ + DEBUG(SSSDBG_TRACE_INTERNAL, + "Terminating idle responder [%p]\n", rctx); + + talloc_free(rctx); + + orderly_shutdown(0); + } + + DEBUG(SSSDBG_TRACE_INTERNAL, + "Re-scheduling the idle timeout for the responder [%p]\n", rctx); + +end: + schedule_responder_idle_timer(rctx); +} + +static errno_t schedule_responder_idle_timer(struct resp_ctx *rctx) +{ + struct timeval tv; + + tv = tevent_timeval_current_ofs(rctx->idle_timeout / 2, 0); + + talloc_zfree(rctx->idle); + rctx->idle = tevent_add_timer(rctx->ev, + rctx, + tv, + responder_idle_handler, + rctx); + if (rctx->idle == NULL) { + DEBUG(SSSDBG_CRIT_FAILURE, + "Failed to allocate time event: responder [%p] shutdown timeout\n", + rctx); + return ENOMEM; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, + "Re-scheduling the idle timeout for the responder [%p]\n", rctx); + + return EOK; +} + +static errno_t setup_responder_idle_timer(struct resp_ctx *rctx) +{ + errno_t ret; + + rctx->last_request_time = time(NULL); + + ret = schedule_responder_idle_timer(rctx); + if (ret != EOK) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Error scheduling the idle timeout for the responder [%p]: " + "%d [%s]\n", + rctx, ret, sss_strerror(ret)); + return ret; + } + + DEBUG(SSSDBG_TRACE_INTERNAL, + "Setting up the idle timeout for the responder [%p]\n", rctx); + + return EOK; +} + static void client_fd_handler(struct tevent_context *ev, struct tevent_fd *fde, uint16_t flags, void *ptr) @@ -358,6 +440,9 @@ static void client_fd_handler(struct tevent_context *ev, struct cli_ctx *cctx = talloc_get_type(ptr, struct cli_ctx); /* Always reset the idle timer on any activity */ + cctx->rctx->last_request_time = time(NULL); + + /* Always reset the idle timer on any activity */ ret = reset_client_idle_timer(cctx); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, @@ -970,6 +1055,47 @@ int sss_process_init(TALLOC_CTX *mem_ctx, rctx->client_idle_timeout = 10; } + if (rctx->socket_activated || rctx->dbus_activated) { + ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path, + CONFDB_RESPONDER_IDLE_TIMEOUT, + CONFDB_RESPONDER_IDLE_DEFAULT_TIMEOUT, + &rctx->idle_timeout); + if (ret != EOK) { + DEBUG(SSSDBG_OP_FAILURE, + "Cannot get the responder idle timeout [%d]: %s\n", + ret, sss_strerror(ret)); + goto fail; + } + + /* Idle timeout set to 0 means that no timeout will be set up to + * the responder */ + if (rctx->idle_timeout == 0) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "Responder idle timeout won't be set up as the " + "responder_idle_timeout is set to 0"); + } else { + /* Ensure that the responder timeout is at least sixty seconds */ + if (rctx->idle_timeout < 60) { + DEBUG(SSSDBG_TRACE_INTERNAL, + "responder_idle_timeout is set to a value lower than " + "the minimum allowed (60s).\n" + "The minimum allowed value will be used."); + + rctx->idle_timeout = 60; + } + + ret = setup_responder_idle_timer(rctx); + if (ret != EOK) { + DEBUG(SSSDBG_MINOR_FAILURE, + "An error ocurrend when setting up the responder's idle " + "timeout for the responder [%p]: %s [%d].\n" + "The responder won't be automatically shutdown after %d " + "seconds inactive. \n", + rctx, sss_strerror(ret), ret, rctx->idle_timeout); + } + } + } + ret = confdb_get_int(rctx->cdb, rctx->confdb_service_path, CONFDB_RESPONDER_GET_DOMAINS_TIMEOUT, GET_DOMAINS_DEFAULT_TIMEOUT, &rctx->domains_timeout); @@ -1023,7 +1149,8 @@ int sss_process_init(TALLOC_CTX *mem_ctx, ret = sss_monitor_init(rctx, rctx->ev, monitor_intf, svc_name, svc_version, MT_SVC_SERVICE, - rctx, NULL, &rctx->mon_conn); + rctx, &rctx->last_request_time, + &rctx->mon_conn); if (ret != EOK) { DEBUG(SSSDBG_FATAL_FAILURE, "fatal error setting up message bus\n"); goto fail; |
