]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #29159 from poettering/socket-pause
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Sep 2023 07:40:27 +0000 (09:40 +0200)
committerGitHub <noreply@github.com>
Tue, 19 Sep 2023 07:40:27 +0000 (09:40 +0200)
core: add new "PollLimit" settings to .socket units

1  2 
src/core/socket.c

diff --combined src/core/socket.c
index 3304af831dbe24ee2111b40940e1d8c4043d5527,3e25cc8d6effb3f8420dee88e4b25d5f223ac0cf..43f412bc895fcd0f362cbafde9926c9ce771755f
@@@ -102,6 -102,9 +102,9 @@@ static void socket_init(Unit *u) 
  
          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) {
@@@ -307,17 -310,20 +310,20 @@@ static int socket_add_extras(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)) {
  
@@@ -767,9 -773,13 +773,13 @@@ static void socket_dump(Unit *u, FILE *
  
          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)
@@@ -1503,9 -1513,9 +1513,9 @@@ static int socket_address_listen_in_cgr
                  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;
@@@ -1761,6 -1771,10 +1771,10 @@@ static int socket_watch_fds(Socket *s) 
  
                          (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;
@@@ -1968,7 -1982,8 +1982,7 @@@ static int socket_spawn(Socket *s, Exec
  }
  
  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;
  }
  
@@@ -2112,9 -2131,9 +2126,9 @@@ static void socket_enter_signal(Socket 
                          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;
  
@@@ -2977,9 -2996,9 +2991,9 @@@ static int socket_accept_do(Socket *s, 
  }
  
  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;
@@@ -3377,6 -3396,10 +3391,6 @@@ static void socket_trigger_notify(Unit 
                  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;
@@@ -3405,13 -3428,18 +3419,13 @@@ char *socket_fdname(Socket *s) 
          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;
  
@@@ -3558,6 -3590,7 +3572,6 @@@ const UnitVTable socket_vtable = 
          .start = socket_start,
          .stop = socket_stop,
  
 -        .kill = socket_kill,
          .clean = socket_clean,
          .can_clean = socket_can_clean,