Skip to content

Commit da3cd87

Browse files
authored
Merge pull request systemd#28129 from poettering/userdb-ratelimit
userdbd: make sure we don't exit under pressure
2 parents 6270b2e + 2543dea commit da3cd87

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

src/userdb/userdbd-manager.c

+41-7
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,18 @@ static int on_sigusr2(sd_event_source *s, const struct signalfd_siginfo *si, voi
4949

5050
assert(s);
5151

52-
(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 */
52+
(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 */
53+
return 0;
54+
}
55+
56+
static int on_deferred_start_worker(sd_event_source *s, uint64_t usec, void *userdata) {
57+
Manager *m = ASSERT_PTR(userdata);
58+
59+
assert(s);
60+
61+
m->deferred_start_worker_event_source = sd_event_source_unref(m->deferred_start_worker_event_source);
62+
63+
(void) start_workers(m, /* explicit_request=*/ false);
5364
return 0;
5465
}
5566

@@ -71,8 +82,8 @@ int manager_new(Manager **ret) {
7182
*m = (Manager) {
7283
.listen_fd = -EBADF,
7384
.worker_ratelimit = {
74-
.interval = 5 * USEC_PER_SEC,
75-
.burst = 50,
85+
.interval = 2 * USEC_PER_SEC,
86+
.burst = 2500,
7687
},
7788
};
7889

@@ -111,6 +122,8 @@ Manager* manager_free(Manager *m) {
111122
set_free(m->workers_fixed);
112123
set_free(m->workers_dynamic);
113124

125+
m->deferred_start_worker_event_source = sd_event_source_unref(m->deferred_start_worker_event_source);
126+
114127
sd_event_unref(m->event);
115128

116129
return mfree(m);
@@ -213,10 +226,31 @@ static int start_workers(Manager *m, bool explicit_request) {
213226
break;
214227

215228
if (!ratelimit_below(&m->worker_ratelimit)) {
216-
/* If we keep starting workers too often, let's fail the whole daemon, something is wrong */
217-
sd_event_exit(m->event, EXIT_FAILURE);
218229

219-
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "Worker threads requested too frequently, something is wrong.");
230+
/* If we keep starting workers too often but none sticks, let's fail the whole
231+
* daemon, something is wrong */
232+
if (n == 0) {
233+
sd_event_exit(m->event, EXIT_FAILURE);
234+
return log_error_errno(SYNTHETIC_ERRNO(EUCLEAN), "Worker threads requested too frequently, but worker count is zero, something is wrong.");
235+
}
236+
237+
/* Otherwise, let's stop spawning more for a while. */
238+
log_warning("Worker threads requested too frequently, not starting new ones for a while.");
239+
240+
if (!m->deferred_start_worker_event_source) {
241+
r = sd_event_add_time(
242+
m->event,
243+
&m->deferred_start_worker_event_source,
244+
CLOCK_MONOTONIC,
245+
ratelimit_end(&m->worker_ratelimit),
246+
/* accuracy_usec= */ 0,
247+
on_deferred_start_worker,
248+
m);
249+
if (r < 0)
250+
return log_error_errno(r, "Failed to allocate deferred start worker event source: %m");
251+
}
252+
253+
break;
220254
}
221255

222256
r = start_one_worker(m);
@@ -281,5 +315,5 @@ int manager_startup(Manager *m) {
281315
if (setsockopt(m->listen_fd, SOL_SOCKET, SO_RCVTIMEO, TIMEVAL_STORE(LISTEN_TIMEOUT_USEC), sizeof(struct timeval)) < 0)
282316
return log_error_errno(errno, "Failed to se SO_RCVTIMEO: %m");
283317

284-
return start_workers(m, false);
318+
return start_workers(m, /* explicit_request= */ false);
285319
}

src/userdb/userdbd-manager.h

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ struct Manager {
2121
int listen_fd;
2222

2323
RateLimit worker_ratelimit;
24+
25+
sd_event_source *deferred_start_worker_event_source;
2426
};
2527

2628
int manager_new(Manager **ret);

0 commit comments

Comments
 (0)