s->trigger_limit.interval = USEC_INFINITY;
s->trigger_limit.burst = UINT_MAX;
+
+ s->poll_limit_interval = USEC_INFINITY;
+ s->poll_limit_burst = UINT_MAX;
}
static void socket_unwatch_control_pid(Socket *s) {
* off the queues, which it might not necessarily do. Moreover, while Accept=no services are supposed to
* process whatever is queued in one go, and thus should normally never have to be started frequently. This is
* different for Accept=yes where each connection is processed by a new service instance, and thus frequent
- * service starts are typical. */
+ * service starts are typical.
+ *
+ * For the poll limit we follow a similar rule, but use 3/4th of the trigger limit parameters, to
+ * trigger this earlier. */
if (s->trigger_limit.interval == USEC_INFINITY)
s->trigger_limit.interval = 2 * USEC_PER_SEC;
+ if (s->trigger_limit.burst == UINT_MAX)
+ s->trigger_limit.burst = s->accept ? 200 : 20;
- if (s->trigger_limit.burst == UINT_MAX) {
- if (s->accept)
- s->trigger_limit.burst = 200;
- else
- s->trigger_limit.burst = 20;
- }
+ if (s->poll_limit_interval == USEC_INFINITY)
+ s->poll_limit_interval = 2 * USEC_PER_SEC;
+ if (s->poll_limit_burst == UINT_MAX)
+ s->poll_limit_burst = s->accept ? 150 : 15;
if (have_non_accept_socket(s)) {
fprintf(f,
"%sTriggerLimitIntervalSec: %s\n"
- "%sTriggerLimitBurst: %u\n",
+ "%sTriggerLimitBurst: %u\n"
+ "%sPollLimitIntervalSec: %s\n"
+ "%sPollLimitBurst: %u\n",
prefix, FORMAT_TIMESPAN(s->trigger_limit.interval, USEC_PER_SEC),
- prefix, s->trigger_limit.burst);
+ prefix, s->trigger_limit.burst,
+ prefix, FORMAT_TIMESPAN(s->poll_limit_interval, USEC_PER_SEC),
+ prefix, s->poll_limit_burst);
str = ip_protocol_to_name(s->socket_protocol);
if (str)
const SocketAddress *address,
const char *label) {
+ _cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
_cleanup_close_pair_ int pair[2] = PIPE_EBADF;
int fd, r;
- pid_t pid;
assert(s);
assert(address);
fd = receive_one_fd(pair[0], 0);
/* We synchronously wait for the helper, as it shouldn't be slow */
- r = wait_for_terminate_and_check("(sd-listen)", pid, WAIT_LOG_ABNORMAL);
+ r = wait_for_terminate_and_check("(sd-listen)", pid.pid, WAIT_LOG_ABNORMAL);
if (r < 0) {
safe_close(fd);
return r;
(void) sd_event_source_set_description(p->event_source, "socket-port-io");
}
+
+ r = sd_event_source_set_ratelimit(p->event_source, s->poll_limit_interval, s->poll_limit_burst);
+ if (r < 0)
+ log_unit_debug_errno(UNIT(s), r, "Failed to set poll limit on I/O event source, ignoring: %m");
}
return 0;
}
static int socket_chown(Socket *s, PidRef *ret_pid) {
- _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
- pid_t pid;
+ _cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
int r;
assert(s);
_exit(EXIT_SUCCESS);
}
- r = pidref_set_pid(&pidref, pid);
- if (r < 0)
- return r;
-
- r = unit_watch_pid(UNIT(s), pidref.pid, /* exclusive= */ true);
+ r = unit_watch_pid(UNIT(s), pid.pid, /* exclusive= */ true);
if (r < 0)
return r;
- *ret_pid = TAKE_PIDREF(pidref);
+ *ret_pid = TAKE_PIDREF(pid);
return 0;
}
UNIT(s),
&s->kill_context,
state_to_kill_operation(s, state),
- -1,
- s->control_pid.pid,
- false);
+ /* main_pid= */ NULL,
+ &s->control_pid,
+ /* main_pid_alien= */ false);
if (r < 0)
goto fail;
}
static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
+ _cleanup_(pidref_done) PidRef pid = PIDREF_NULL;
_cleanup_close_pair_ int pair[2] = PIPE_EBADF;
int cfd, r;
- pid_t pid;
assert(s);
assert(p);
cfd = receive_one_fd(pair[0], 0);
/* We synchronously wait for the helper, as it shouldn't be slow */
- r = wait_for_terminate_and_check("(sd-accept)", pid, WAIT_LOG_ABNORMAL);
+ r = wait_for_terminate_and_check("(sd-accept)", pid.pid, WAIT_LOG_ABNORMAL);
if (r < 0) {
safe_close(cfd);
return r;
socket_set_state(s, SOCKET_RUNNING);
}
-static int socket_kill(Unit *u, KillWho who, int signo, int code, int value, sd_bus_error *error) {
- return unit_kill_common(u, who, signo, code, value, -1, SOCKET(u)->control_pid.pid, error);
-}
-
static int socket_get_timeout(Unit *u, usec_t *timeout) {
Socket *s = SOCKET(u);
usec_t t;
return s->fdname ?: UNIT(s)->id;
}
-static int socket_control_pid(Unit *u) {
- Socket *s = SOCKET(u);
-
- assert(s);
-
- return s->control_pid.pid;
+static PidRef *socket_control_pid(Unit *u) {
+ return &ASSERT_PTR(SOCKET(u))->control_pid;
}
static int socket_clean(Unit *u, ExecCleanMask mask) {
_cleanup_strv_free_ char **l = NULL;
Socket *s = SOCKET(u);
- pid_t pid;
int r;
assert(s);
if (r < 0)
goto fail;
- r = unit_fork_and_watch_rm_rf(u, l, &pid);
- if (r < 0)
- goto fail;
-
- r = pidref_set_pid(&s->control_pid, pid);
+ r = unit_fork_and_watch_rm_rf(u, l, &s->control_pid);
if (r < 0)
goto fail;
.start = socket_start,
.stop = socket_stop,
- .kill = socket_kill,
.clean = socket_clean,
.can_clean = socket_can_clean,