LCOV - code coverage report
Current view: top level - core - scope.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 100 306 32.7 %
Date: 2019-08-23 13:36:53 Functions: 13 28 46.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 57 295 19.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <unistd.h>
       5                 :            : 
       6                 :            : #include "alloc-util.h"
       7                 :            : #include "dbus-scope.h"
       8                 :            : #include "dbus-unit.h"
       9                 :            : #include "load-dropin.h"
      10                 :            : #include "log.h"
      11                 :            : #include "scope.h"
      12                 :            : #include "serialize.h"
      13                 :            : #include "special.h"
      14                 :            : #include "string-table.h"
      15                 :            : #include "string-util.h"
      16                 :            : #include "strv.h"
      17                 :            : #include "unit-name.h"
      18                 :            : #include "unit.h"
      19                 :            : 
      20                 :            : static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = {
      21                 :            :         [SCOPE_DEAD] = UNIT_INACTIVE,
      22                 :            :         [SCOPE_RUNNING] = UNIT_ACTIVE,
      23                 :            :         [SCOPE_ABANDONED] = UNIT_ACTIVE,
      24                 :            :         [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING,
      25                 :            :         [SCOPE_STOP_SIGKILL] = UNIT_DEACTIVATING,
      26                 :            :         [SCOPE_FAILED] = UNIT_FAILED
      27                 :            : };
      28                 :            : 
      29                 :            : static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata);
      30                 :            : 
      31                 :         44 : static void scope_init(Unit *u) {
      32                 :         44 :         Scope *s = SCOPE(u);
      33                 :            : 
      34         [ -  + ]:         44 :         assert(u);
      35         [ -  + ]:         44 :         assert(u->load_state == UNIT_STUB);
      36                 :            : 
      37                 :         44 :         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
      38                 :         44 :         u->ignore_on_isolate = true;
      39                 :         44 : }
      40                 :            : 
      41                 :         44 : static void scope_done(Unit *u) {
      42                 :         44 :         Scope *s = SCOPE(u);
      43                 :            : 
      44         [ -  + ]:         44 :         assert(u);
      45                 :            : 
      46                 :         44 :         s->controller = mfree(s->controller);
      47                 :         44 :         s->controller_track = sd_bus_track_unref(s->controller_track);
      48                 :            : 
      49                 :         44 :         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
      50                 :         44 : }
      51                 :            : 
      52                 :          0 : static int scope_arm_timer(Scope *s, usec_t usec) {
      53                 :            :         int r;
      54                 :            : 
      55         [ #  # ]:          0 :         assert(s);
      56                 :            : 
      57         [ #  # ]:          0 :         if (s->timer_event_source) {
      58                 :          0 :                 r = sd_event_source_set_time(s->timer_event_source, usec);
      59         [ #  # ]:          0 :                 if (r < 0)
      60                 :          0 :                         return r;
      61                 :            : 
      62                 :          0 :                 return sd_event_source_set_enabled(s->timer_event_source, SD_EVENT_ONESHOT);
      63                 :            :         }
      64                 :            : 
      65         [ #  # ]:          0 :         if (usec == USEC_INFINITY)
      66                 :          0 :                 return 0;
      67                 :            : 
      68                 :          0 :         r = sd_event_add_time(
      69         [ #  # ]:          0 :                         UNIT(s)->manager->event,
      70                 :            :                         &s->timer_event_source,
      71                 :            :                         CLOCK_MONOTONIC,
      72                 :            :                         usec, 0,
      73                 :            :                         scope_dispatch_timer, s);
      74         [ #  # ]:          0 :         if (r < 0)
      75                 :          0 :                 return r;
      76                 :            : 
      77                 :          0 :         (void) sd_event_source_set_description(s->timer_event_source, "scope-timer");
      78                 :            : 
      79                 :          0 :         return 0;
      80                 :            : }
      81                 :            : 
      82                 :         44 : static void scope_set_state(Scope *s, ScopeState state) {
      83                 :            :         ScopeState old_state;
      84         [ -  + ]:         44 :         assert(s);
      85                 :            : 
      86         [ +  - ]:         44 :         if (s->state != state)
      87         [ +  - ]:         44 :                 bus_unit_send_pending_change_signal(UNIT(s), false);
      88                 :            : 
      89                 :         44 :         old_state = s->state;
      90                 :         44 :         s->state = state;
      91                 :            : 
      92   [ -  +  +  - ]:         44 :         if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
      93                 :         44 :                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
      94                 :            : 
      95   [ -  +  -  + ]:         44 :         if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED)) {
      96         [ #  # ]:          0 :                 unit_unwatch_all_pids(UNIT(s));
      97         [ #  # ]:          0 :                 unit_dequeue_rewatch_pids(UNIT(s));
      98                 :            :         }
      99                 :            : 
     100         [ +  - ]:         44 :         if (state != old_state)
     101   [ +  +  +  - ]:         44 :                 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
     102                 :            : 
     103         [ +  - ]:         44 :         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
     104                 :         44 : }
     105                 :            : 
     106                 :         44 : static int scope_add_default_dependencies(Scope *s) {
     107                 :            :         int r;
     108                 :            : 
     109         [ -  + ]:         44 :         assert(s);
     110                 :            : 
     111   [ +  -  +  - ]:         44 :         if (!UNIT(s)->default_dependencies)
     112                 :         44 :                 return 0;
     113                 :            : 
     114                 :            :         /* Make sure scopes are unloaded on shutdown */
     115                 :          0 :         r = unit_add_two_dependencies_by_name(
     116         [ #  # ]:          0 :                         UNIT(s),
     117                 :            :                         UNIT_BEFORE, UNIT_CONFLICTS,
     118                 :            :                         SPECIAL_SHUTDOWN_TARGET, true,
     119                 :            :                         UNIT_DEPENDENCY_DEFAULT);
     120         [ #  # ]:          0 :         if (r < 0)
     121                 :          0 :                 return r;
     122                 :            : 
     123                 :          0 :         return 0;
     124                 :            : }
     125                 :            : 
     126                 :         44 : static int scope_verify(Scope *s) {
     127         [ -  + ]:         44 :         assert(s);
     128                 :            : 
     129   [ +  -  -  + ]:         44 :         if (UNIT(s)->load_state != UNIT_LOADED)
     130                 :          0 :                 return 0;
     131                 :            : 
     132   [ +  -  +  - ]:         44 :         if (set_isempty(UNIT(s)->pids) &&
     133   [ +  -  +  - ]:         44 :             !MANAGER_IS_RELOADING(UNIT(s)->manager) &&
     134   [ +  -  -  + ]:         44 :             !unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE)) {
     135   [ #  #  #  # ]:          0 :                 log_unit_error(UNIT(s), "Scope has no PIDs. Refusing.");
     136                 :          0 :                 return -ENOENT;
     137                 :            :         }
     138                 :            : 
     139                 :         44 :         return 0;
     140                 :            : }
     141                 :            : 
     142                 :         44 : static int scope_load_init_scope(Unit *u) {
     143         [ -  + ]:         44 :         assert(u);
     144                 :            : 
     145         [ -  + ]:         44 :         if (!unit_has_name(u, SPECIAL_INIT_SCOPE))
     146                 :          0 :                 return 0;
     147                 :            : 
     148                 :         44 :         u->transient = true;
     149                 :         44 :         u->perpetual = true;
     150                 :            : 
     151                 :            :         /* init.scope is a bit special, as it has to stick around forever. Because of its special semantics we
     152                 :            :          * synthesize it here, instead of relying on the unit file on disk. */
     153                 :            : 
     154                 :         44 :         u->default_dependencies = false;
     155                 :            : 
     156                 :            :         /* Prettify things, if we can. */
     157         [ +  - ]:         44 :         if (!u->description)
     158                 :         44 :                 u->description = strdup("System and Service Manager");
     159         [ +  - ]:         44 :         if (!u->documentation)
     160                 :         44 :                 (void) strv_extend(&u->documentation, "man:systemd(1)");
     161                 :            : 
     162                 :         44 :         return 1;
     163                 :            : }
     164                 :            : 
     165                 :         44 : static int scope_load(Unit *u) {
     166                 :         44 :         Scope *s = SCOPE(u);
     167                 :            :         int r;
     168                 :            : 
     169         [ -  + ]:         44 :         assert(s);
     170         [ -  + ]:         44 :         assert(u->load_state == UNIT_STUB);
     171                 :            : 
     172   [ -  +  #  # ]:         44 :         if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
     173                 :            :                 /* Refuse to load non-transient scope units, but allow them while reloading. */
     174                 :          0 :                 return -ENOENT;
     175                 :            : 
     176                 :         44 :         r = scope_load_init_scope(u);
     177         [ -  + ]:         44 :         if (r < 0)
     178                 :          0 :                 return r;
     179                 :         44 :         r = unit_load_fragment_and_dropin_optional(u);
     180         [ -  + ]:         44 :         if (r < 0)
     181                 :          0 :                 return r;
     182                 :            : 
     183         [ +  - ]:         44 :         if (u->load_state == UNIT_LOADED) {
     184                 :         44 :                 r = unit_patch_contexts(u);
     185         [ -  + ]:         44 :                 if (r < 0)
     186                 :          0 :                         return r;
     187                 :            : 
     188                 :         44 :                 r = unit_set_default_slice(u);
     189         [ -  + ]:         44 :                 if (r < 0)
     190                 :          0 :                         return r;
     191                 :            : 
     192                 :         44 :                 r = scope_add_default_dependencies(s);
     193         [ -  + ]:         44 :                 if (r < 0)
     194                 :          0 :                         return r;
     195                 :            :         }
     196                 :            : 
     197                 :         44 :         return scope_verify(s);
     198                 :            : }
     199                 :            : 
     200                 :         44 : static int scope_coldplug(Unit *u) {
     201                 :         44 :         Scope *s = SCOPE(u);
     202                 :            :         int r;
     203                 :            : 
     204         [ -  + ]:         44 :         assert(s);
     205         [ -  + ]:         44 :         assert(s->state == SCOPE_DEAD);
     206                 :            : 
     207         [ -  + ]:         44 :         if (s->deserialized_state == s->state)
     208                 :          0 :                 return 0;
     209                 :            : 
     210   [ -  +  -  + ]:         44 :         if (IN_SET(s->deserialized_state, SCOPE_STOP_SIGKILL, SCOPE_STOP_SIGTERM)) {
     211                 :          0 :                 r = scope_arm_timer(s, usec_add(u->state_change_timestamp.monotonic, s->timeout_stop_usec));
     212         [ #  # ]:          0 :                 if (r < 0)
     213                 :          0 :                         return r;
     214                 :            :         }
     215                 :            : 
     216   [ -  +  +  - ]:         44 :         if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
     217                 :         44 :                 (void) unit_enqueue_rewatch_pids(u);
     218                 :            : 
     219                 :         44 :         bus_scope_track_controller(s);
     220                 :            : 
     221                 :         44 :         scope_set_state(s, s->deserialized_state);
     222                 :         44 :         return 0;
     223                 :            : }
     224                 :            : 
     225                 :         24 : static void scope_dump(Unit *u, FILE *f, const char *prefix) {
     226                 :         24 :         Scope *s = SCOPE(u);
     227                 :            : 
     228         [ -  + ]:         24 :         assert(s);
     229         [ -  + ]:         24 :         assert(f);
     230                 :            : 
     231                 :         24 :         fprintf(f,
     232                 :            :                 "%sScope State: %s\n"
     233                 :            :                 "%sResult: %s\n",
     234                 :            :                 prefix, scope_state_to_string(s->state),
     235                 :            :                 prefix, scope_result_to_string(s->result));
     236                 :            : 
     237                 :         24 :         cgroup_context_dump(&s->cgroup_context, f, prefix);
     238                 :         24 :         kill_context_dump(&s->kill_context, f, prefix);
     239                 :         24 : }
     240                 :            : 
     241                 :          0 : static void scope_enter_dead(Scope *s, ScopeResult f) {
     242         [ #  # ]:          0 :         assert(s);
     243                 :            : 
     244         [ #  # ]:          0 :         if (s->result == SCOPE_SUCCESS)
     245                 :          0 :                 s->result = f;
     246                 :            : 
     247         [ #  # ]:          0 :         unit_log_result(UNIT(s), s->result == SCOPE_SUCCESS, scope_result_to_string(s->result));
     248         [ #  # ]:          0 :         scope_set_state(s, s->result != SCOPE_SUCCESS ? SCOPE_FAILED : SCOPE_DEAD);
     249                 :          0 : }
     250                 :            : 
     251                 :          0 : static void scope_enter_signal(Scope *s, ScopeState state, ScopeResult f) {
     252                 :          0 :         bool skip_signal = false;
     253                 :            :         int r;
     254                 :            : 
     255         [ #  # ]:          0 :         assert(s);
     256                 :            : 
     257         [ #  # ]:          0 :         if (s->result == SCOPE_SUCCESS)
     258                 :          0 :                 s->result = f;
     259                 :            : 
     260                 :            :         /* Before sending any signal, make sure we track all members of this cgroup */
     261         [ #  # ]:          0 :         (void) unit_watch_all_pids(UNIT(s));
     262                 :            : 
     263                 :            :         /* Also, enqueue a job that we recheck all our PIDs a bit later, given that it's likely some processes have
     264                 :            :          * died now */
     265         [ #  # ]:          0 :         (void) unit_enqueue_rewatch_pids(UNIT(s));
     266                 :            : 
     267                 :            :         /* If we have a controller set let's ask the controller nicely to terminate the scope, instead of us going
     268                 :            :          * directly into SIGTERM berserk mode */
     269         [ #  # ]:          0 :         if (state == SCOPE_STOP_SIGTERM)
     270                 :          0 :                 skip_signal = bus_scope_send_request_stop(s) > 0;
     271                 :            : 
     272         [ #  # ]:          0 :         if (skip_signal)
     273                 :          0 :                 r = 1; /* wait */
     274                 :            :         else {
     275         [ #  # ]:          0 :                 r = unit_kill_context(
     276         [ #  # ]:          0 :                                 UNIT(s),
     277                 :            :                                 &s->kill_context,
     278                 :            :                                 state != SCOPE_STOP_SIGTERM ? KILL_KILL :
     279                 :          0 :                                 s->was_abandoned            ? KILL_TERMINATE_AND_LOG :
     280                 :            :                                                               KILL_TERMINATE,
     281                 :            :                                 -1, -1, false);
     282         [ #  # ]:          0 :                 if (r < 0)
     283                 :          0 :                         goto fail;
     284                 :            :         }
     285                 :            : 
     286         [ #  # ]:          0 :         if (r > 0) {
     287                 :          0 :                 r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_stop_usec));
     288         [ #  # ]:          0 :                 if (r < 0)
     289                 :          0 :                         goto fail;
     290                 :            : 
     291                 :          0 :                 scope_set_state(s, state);
     292         [ #  # ]:          0 :         } else if (state == SCOPE_STOP_SIGTERM)
     293                 :          0 :                 scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_SUCCESS);
     294                 :            :         else
     295                 :          0 :                 scope_enter_dead(s, SCOPE_SUCCESS);
     296                 :            : 
     297                 :          0 :         return;
     298                 :            : 
     299                 :          0 : fail:
     300   [ #  #  #  # ]:          0 :         log_unit_warning_errno(UNIT(s), r, "Failed to kill processes: %m");
     301                 :            : 
     302                 :          0 :         scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
     303                 :            : }
     304                 :            : 
     305                 :          0 : static int scope_start(Unit *u) {
     306                 :          0 :         Scope *s = SCOPE(u);
     307                 :            :         int r;
     308                 :            : 
     309         [ #  # ]:          0 :         assert(s);
     310                 :            : 
     311         [ #  # ]:          0 :         if (unit_has_name(u, SPECIAL_INIT_SCOPE))
     312                 :          0 :                 return -EPERM;
     313                 :            : 
     314         [ #  # ]:          0 :         if (s->state == SCOPE_FAILED)
     315                 :          0 :                 return -EPERM;
     316                 :            : 
     317                 :            :         /* We can't fulfill this right now, please try again later */
     318   [ #  #  #  # ]:          0 :         if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
     319                 :          0 :                 return -EAGAIN;
     320                 :            : 
     321         [ #  # ]:          0 :         assert(s->state == SCOPE_DEAD);
     322                 :            : 
     323   [ #  #  #  # ]:          0 :         if (!u->transient && !MANAGER_IS_RELOADING(u->manager))
     324                 :          0 :                 return -ENOENT;
     325                 :            : 
     326                 :          0 :         (void) bus_scope_track_controller(s);
     327                 :            : 
     328                 :          0 :         r = unit_acquire_invocation_id(u);
     329         [ #  # ]:          0 :         if (r < 0)
     330                 :          0 :                 return r;
     331                 :            : 
     332                 :          0 :         (void) unit_realize_cgroup(u);
     333                 :          0 :         (void) unit_reset_accounting(u);
     334                 :            : 
     335                 :          0 :         unit_export_state_files(u);
     336                 :            : 
     337                 :          0 :         r = unit_attach_pids_to_cgroup(u, u->pids, NULL);
     338         [ #  # ]:          0 :         if (r < 0) {
     339         [ #  # ]:          0 :                 log_unit_warning_errno(u, r, "Failed to add PIDs to scope's control group: %m");
     340                 :          0 :                 scope_enter_dead(s, SCOPE_FAILURE_RESOURCES);
     341                 :          0 :                 return r;
     342                 :            :         }
     343                 :            : 
     344                 :          0 :         s->result = SCOPE_SUCCESS;
     345                 :            : 
     346                 :          0 :         scope_set_state(s, SCOPE_RUNNING);
     347                 :            : 
     348                 :            :         /* Start watching the PIDs currently in the scope */
     349                 :          0 :         (void) unit_enqueue_rewatch_pids(u);
     350                 :          0 :         return 1;
     351                 :            : }
     352                 :            : 
     353                 :          0 : static int scope_stop(Unit *u) {
     354                 :          0 :         Scope *s = SCOPE(u);
     355                 :            : 
     356         [ #  # ]:          0 :         assert(s);
     357                 :            : 
     358   [ #  #  #  # ]:          0 :         if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
     359                 :          0 :                 return 0;
     360                 :            : 
     361   [ #  #  #  # ]:          0 :         assert(IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED));
     362                 :            : 
     363                 :          0 :         scope_enter_signal(s, SCOPE_STOP_SIGTERM, SCOPE_SUCCESS);
     364                 :          0 :         return 1;
     365                 :            : }
     366                 :            : 
     367                 :          0 : static void scope_reset_failed(Unit *u) {
     368                 :          0 :         Scope *s = SCOPE(u);
     369                 :            : 
     370         [ #  # ]:          0 :         assert(s);
     371                 :            : 
     372         [ #  # ]:          0 :         if (s->state == SCOPE_FAILED)
     373                 :          0 :                 scope_set_state(s, SCOPE_DEAD);
     374                 :            : 
     375                 :          0 :         s->result = SCOPE_SUCCESS;
     376                 :          0 : }
     377                 :            : 
     378                 :          0 : static int scope_kill(Unit *u, KillWho who, int signo, sd_bus_error *error) {
     379                 :          0 :         return unit_kill_common(u, who, signo, -1, -1, error);
     380                 :            : }
     381                 :            : 
     382                 :          0 : static int scope_get_timeout(Unit *u, usec_t *timeout) {
     383                 :          0 :         Scope *s = SCOPE(u);
     384                 :            :         usec_t t;
     385                 :            :         int r;
     386                 :            : 
     387         [ #  # ]:          0 :         if (!s->timer_event_source)
     388                 :          0 :                 return 0;
     389                 :            : 
     390                 :          0 :         r = sd_event_source_get_time(s->timer_event_source, &t);
     391         [ #  # ]:          0 :         if (r < 0)
     392                 :          0 :                 return r;
     393         [ #  # ]:          0 :         if (t == USEC_INFINITY)
     394                 :          0 :                 return 0;
     395                 :            : 
     396                 :          0 :         *timeout = t;
     397                 :          0 :         return 1;
     398                 :            : }
     399                 :            : 
     400                 :          0 : static int scope_serialize(Unit *u, FILE *f, FDSet *fds) {
     401                 :          0 :         Scope *s = SCOPE(u);
     402                 :            : 
     403         [ #  # ]:          0 :         assert(s);
     404         [ #  # ]:          0 :         assert(f);
     405         [ #  # ]:          0 :         assert(fds);
     406                 :            : 
     407                 :          0 :         (void) serialize_item(f, "state", scope_state_to_string(s->state));
     408                 :          0 :         (void) serialize_bool(f, "was-abandoned", s->was_abandoned);
     409                 :            : 
     410         [ #  # ]:          0 :         if (s->controller)
     411                 :          0 :                 (void) serialize_item(f, "controller", s->controller);
     412                 :            : 
     413                 :          0 :         return 0;
     414                 :            : }
     415                 :            : 
     416                 :          0 : static int scope_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
     417                 :          0 :         Scope *s = SCOPE(u);
     418                 :            :         int r;
     419                 :            : 
     420         [ #  # ]:          0 :         assert(u);
     421         [ #  # ]:          0 :         assert(key);
     422         [ #  # ]:          0 :         assert(value);
     423         [ #  # ]:          0 :         assert(fds);
     424                 :            : 
     425         [ #  # ]:          0 :         if (streq(key, "state")) {
     426                 :            :                 ScopeState state;
     427                 :            : 
     428                 :          0 :                 state = scope_state_from_string(value);
     429         [ #  # ]:          0 :                 if (state < 0)
     430         [ #  # ]:          0 :                         log_unit_debug(u, "Failed to parse state value: %s", value);
     431                 :            :                 else
     432                 :          0 :                         s->deserialized_state = state;
     433                 :            : 
     434         [ #  # ]:          0 :         } else if (streq(key, "was-abandoned")) {
     435                 :            :                 int k;
     436                 :            : 
     437                 :          0 :                 k = parse_boolean(value);
     438         [ #  # ]:          0 :                 if (k < 0)
     439         [ #  # ]:          0 :                         log_unit_debug(u, "Failed to parse boolean value: %s", value);
     440                 :            :                 else
     441                 :          0 :                         s->was_abandoned = k;
     442         [ #  # ]:          0 :         } else if (streq(key, "controller")) {
     443                 :            : 
     444                 :          0 :                 r = free_and_strdup(&s->controller, value);
     445         [ #  # ]:          0 :                 if (r < 0)
     446                 :          0 :                         return log_oom();
     447                 :            : 
     448                 :            :         } else
     449         [ #  # ]:          0 :                 log_unit_debug(u, "Unknown serialization key: %s", key);
     450                 :            : 
     451                 :          0 :         return 0;
     452                 :            : }
     453                 :            : 
     454                 :          0 : static void scope_notify_cgroup_empty_event(Unit *u) {
     455                 :          0 :         Scope *s = SCOPE(u);
     456         [ #  # ]:          0 :         assert(u);
     457                 :            : 
     458         [ #  # ]:          0 :         log_unit_debug(u, "cgroup is empty");
     459                 :            : 
     460   [ #  #  #  # ]:          0 :         if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
     461                 :          0 :                 scope_enter_dead(s, SCOPE_SUCCESS);
     462                 :          0 : }
     463                 :            : 
     464                 :          0 : static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) {
     465         [ #  # ]:          0 :         assert(u);
     466                 :            : 
     467                 :            :         /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to
     468                 :            :          * watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original
     469                 :            :          * process we watched was probably the parent of them, and they are hence now our children. */
     470                 :            : 
     471                 :          0 :         (void) unit_enqueue_rewatch_pids(u);
     472                 :          0 : }
     473                 :            : 
     474                 :          0 : static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *userdata) {
     475                 :          0 :         Scope *s = SCOPE(userdata);
     476                 :            : 
     477         [ #  # ]:          0 :         assert(s);
     478         [ #  # ]:          0 :         assert(s->timer_event_source == source);
     479                 :            : 
     480      [ #  #  # ]:          0 :         switch (s->state) {
     481                 :            : 
     482                 :          0 :         case SCOPE_STOP_SIGTERM:
     483         [ #  # ]:          0 :                 if (s->kill_context.send_sigkill) {
     484   [ #  #  #  # ]:          0 :                         log_unit_warning(UNIT(s), "Stopping timed out. Killing.");
     485                 :          0 :                         scope_enter_signal(s, SCOPE_STOP_SIGKILL, SCOPE_FAILURE_TIMEOUT);
     486                 :            :                 } else {
     487   [ #  #  #  # ]:          0 :                         log_unit_warning(UNIT(s), "Stopping timed out. Skipping SIGKILL.");
     488                 :          0 :                         scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
     489                 :            :                 }
     490                 :            : 
     491                 :          0 :                 break;
     492                 :            : 
     493                 :          0 :         case SCOPE_STOP_SIGKILL:
     494   [ #  #  #  # ]:          0 :                 log_unit_warning(UNIT(s), "Still around after SIGKILL. Ignoring.");
     495                 :          0 :                 scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT);
     496                 :          0 :                 break;
     497                 :            : 
     498                 :          0 :         default:
     499                 :          0 :                 assert_not_reached("Timeout at wrong time.");
     500                 :            :         }
     501                 :            : 
     502                 :          0 :         return 0;
     503                 :            : }
     504                 :            : 
     505                 :          0 : int scope_abandon(Scope *s) {
     506         [ #  # ]:          0 :         assert(s);
     507                 :            : 
     508   [ #  #  #  # ]:          0 :         if (unit_has_name(UNIT(s), SPECIAL_INIT_SCOPE))
     509                 :          0 :                 return -EPERM;
     510                 :            : 
     511   [ #  #  #  # ]:          0 :         if (!IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED))
     512                 :          0 :                 return -ESTALE;
     513                 :            : 
     514                 :          0 :         s->was_abandoned = true;
     515                 :            : 
     516                 :          0 :         s->controller = mfree(s->controller);
     517                 :          0 :         s->controller_track = sd_bus_track_unref(s->controller_track);
     518                 :            : 
     519                 :          0 :         scope_set_state(s, SCOPE_ABANDONED);
     520                 :            : 
     521                 :            :         /* The client is no longer watching the remaining processes, so let's step in here, under the assumption that
     522                 :            :          * the remaining processes will be sooner or later reassigned to us as parent. */
     523         [ #  # ]:          0 :         (void) unit_enqueue_rewatch_pids(UNIT(s));
     524                 :            : 
     525                 :          0 :         return 0;
     526                 :            : }
     527                 :            : 
     528                 :        387 : _pure_ static UnitActiveState scope_active_state(Unit *u) {
     529         [ -  + ]:        387 :         assert(u);
     530                 :            : 
     531                 :        387 :         return state_translation_table[SCOPE(u)->state];
     532                 :            : }
     533                 :            : 
     534                 :          0 : _pure_ static const char *scope_sub_state_to_string(Unit *u) {
     535         [ #  # ]:          0 :         assert(u);
     536                 :            : 
     537                 :          0 :         return scope_state_to_string(SCOPE(u)->state);
     538                 :            : }
     539                 :            : 
     540                 :         44 : static void scope_enumerate_perpetual(Manager *m) {
     541                 :            :         Unit *u;
     542                 :            :         int r;
     543                 :            : 
     544         [ -  + ]:         44 :         assert(m);
     545                 :            : 
     546                 :            :         /* Let's unconditionally add the "init.scope" special unit
     547                 :            :          * that encapsulates PID 1. Note that PID 1 already is in the
     548                 :            :          * cgroup for this, we hence just need to allocate the object
     549                 :            :          * for it and that's it. */
     550                 :            : 
     551                 :         44 :         u = manager_get_unit(m, SPECIAL_INIT_SCOPE);
     552         [ +  - ]:         44 :         if (!u) {
     553                 :         44 :                 r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u);
     554         [ -  + ]:         44 :                 if (r < 0)  {
     555         [ #  # ]:          0 :                         log_error_errno(r, "Failed to allocate the special " SPECIAL_INIT_SCOPE " unit: %m");
     556                 :          0 :                         return;
     557                 :            :                 }
     558                 :            :         }
     559                 :            : 
     560                 :         44 :         u->transient = true;
     561                 :         44 :         u->perpetual = true;
     562                 :         44 :         SCOPE(u)->deserialized_state = SCOPE_RUNNING;
     563                 :            : 
     564                 :         44 :         unit_add_to_load_queue(u);
     565                 :         44 :         unit_add_to_dbus_queue(u);
     566                 :            : }
     567                 :            : 
     568                 :            : static const char* const scope_result_table[_SCOPE_RESULT_MAX] = {
     569                 :            :         [SCOPE_SUCCESS] = "success",
     570                 :            :         [SCOPE_FAILURE_RESOURCES] = "resources",
     571                 :            :         [SCOPE_FAILURE_TIMEOUT] = "timeout",
     572                 :            : };
     573                 :            : 
     574   [ +  +  +  + ]:         64 : DEFINE_STRING_TABLE_LOOKUP(scope_result, ScopeResult);
     575                 :            : 
     576                 :            : const UnitVTable scope_vtable = {
     577                 :            :         .object_size = sizeof(Scope),
     578                 :            :         .cgroup_context_offset = offsetof(Scope, cgroup_context),
     579                 :            :         .kill_context_offset = offsetof(Scope, kill_context),
     580                 :            : 
     581                 :            :         .sections =
     582                 :            :                 "Unit\0"
     583                 :            :                 "Scope\0"
     584                 :            :                 "Install\0",
     585                 :            :         .private_section = "Scope",
     586                 :            : 
     587                 :            :         .can_transient = true,
     588                 :            :         .can_delegate = true,
     589                 :            :         .once_only = true,
     590                 :            : 
     591                 :            :         .init = scope_init,
     592                 :            :         .load = scope_load,
     593                 :            :         .done = scope_done,
     594                 :            : 
     595                 :            :         .coldplug = scope_coldplug,
     596                 :            : 
     597                 :            :         .dump = scope_dump,
     598                 :            : 
     599                 :            :         .start = scope_start,
     600                 :            :         .stop = scope_stop,
     601                 :            : 
     602                 :            :         .kill = scope_kill,
     603                 :            : 
     604                 :            :         .get_timeout = scope_get_timeout,
     605                 :            : 
     606                 :            :         .serialize = scope_serialize,
     607                 :            :         .deserialize_item = scope_deserialize_item,
     608                 :            : 
     609                 :            :         .active_state = scope_active_state,
     610                 :            :         .sub_state_to_string = scope_sub_state_to_string,
     611                 :            : 
     612                 :            :         .sigchld_event = scope_sigchld_event,
     613                 :            : 
     614                 :            :         .reset_failed = scope_reset_failed,
     615                 :            : 
     616                 :            :         .notify_cgroup_empty = scope_notify_cgroup_empty_event,
     617                 :            : 
     618                 :            :         .bus_vtable = bus_scope_vtable,
     619                 :            :         .bus_set_property = bus_scope_set_property,
     620                 :            :         .bus_commit_properties = bus_scope_commit_properties,
     621                 :            : 
     622                 :            :         .enumerate_perpetual = scope_enumerate_perpetual,
     623                 :            : };

Generated by: LCOV version 1.14