1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

Merge pull request #28129 from poettering/userdb-ratelimit

userdbd: make sure we don't exit under pressure
This commit is contained in:
Lennart Poettering 2023-06-23 09:53:21 +02:00 committed by GitHub
commit da3cd87ab4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 7 deletions

View File

@ -49,7 +49,18 @@ static int on_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, voi
assert(s);
(void) start_workers(m, true); /* Workers told us there's more work, let's add one more worker as long as we are below the high watermark */
(void) start_workers(m, /* explicit_request=*/ true); /* Workers told us there's more work, let's add one more worker as long as we are below the high watermark */
return 0;
}
static int on_deferred_start_worker(sd_event_source *s, uint64_t usec, void *userdata) {
Manager *m = ASSERT_PTR(userdata);
assert(s);
m->deferred_start_worker_event_source = sd_event_source_unref(m->deferred_start_worker_event_source);
(void) start_workers(m, /* explicit_request=*/ false);
return 0;
}
@ -71,8 +82,8 @@ int manager_new(Manager **ret) {
*m = (Manager) {
.listen_fd = -EBADF,
.worker_ratelimit = {
.interval = 5 * USEC_PER_SEC,
.burst = 50,
.interval = 2 * USEC_PER_SEC,
.burst = 2500,
},
};
@ -111,6 +122,8 @@ Manager* manager_free(Manager *m) {
set_free(m->workers_fixed);
set_free(m->workers_dynamic);
m->deferred_start_worker_event_source = sd_event_source_unref(m->deferred_start_worker_event_source);
sd_event_unref(m->event);
return mfree(m);
@ -213,10 +226,31 @@ static int start_workers(Manager *m, bool explicit_request) {
break;
if (!ratelimit_below(&m->worker_ratelimit)) {
/* If we keep starting workers too often, let's fail the whole daemon, something is wrong */
sd_event_exit(m->event, EXIT_FAILURE);
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "Worker threads requested too frequently, something is wrong.");
/* If we keep starting workers too often but none sticks, let's fail the whole
* daemon, something is wrong */
if (n == 0) {
sd_event_exit(m->event, EXIT_FAILURE);
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "Worker threads requested too frequently, but worker count is zero, something is wrong.");
}
/* Otherwise, let's stop spawning more for a while. */
log_warning("Worker threads requested too frequently, not starting new ones for a while.");
if (!m->deferred_start_worker_event_source) {
r = sd_event_add_time(
m->event,
&m->deferred_start_worker_event_source,
CLOCK_MONOTONIC,
ratelimit_end(&m->worker_ratelimit),
/* accuracy_usec= */ 0,
on_deferred_start_worker,
m);
if (r < 0)
return log_error_errno(r, "Failed to allocate deferred start worker event source: %m");
}
break;
}
r = start_one_worker(m);
@ -281,5 +315,5 @@ int manager_startup(Manager *m) {
if (setsockopt(m->listen_fd, SOL_SOCKET, SO_RCVTIMEO, TIMEVAL_STORE(LISTEN_TIMEOUT_USEC), sizeof(struct timeval)) < 0)
return log_error_errno(errno, "Failed to se SO_RCVTIMEO: %m");
return start_workers(m, false);
return start_workers(m, /* explicit_request= */ false);
}

View File

@ -21,6 +21,8 @@ struct Manager {
int listen_fd;
RateLimit worker_ratelimit;
sd_event_source *deferred_start_worker_event_source;
};
int manager_new(Manager **ret);