LCOV - code coverage report
Current view: top level - core - scope.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 100 306 32.7 %
Date: 2019-08-22 15:41:25 Functions: 13 28 46.4 %

          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          11 : static void scope_init(Unit *u) {
      32          11 :         Scope *s = SCOPE(u);
      33             : 
      34          11 :         assert(u);
      35          11 :         assert(u->load_state == UNIT_STUB);
      36             : 
      37          11 :         s->timeout_stop_usec = u->manager->default_timeout_stop_usec;
      38          11 :         u->ignore_on_isolate = true;
      39          11 : }
      40             : 
      41          11 : static void scope_done(Unit *u) {
      42          11 :         Scope *s = SCOPE(u);
      43             : 
      44          11 :         assert(u);
      45             : 
      46          11 :         s->controller = mfree(s->controller);
      47          11 :         s->controller_track = sd_bus_track_unref(s->controller_track);
      48             : 
      49          11 :         s->timer_event_source = sd_event_source_unref(s->timer_event_source);
      50          11 : }
      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          11 : static void scope_set_state(Scope *s, ScopeState state) {
      83             :         ScopeState old_state;
      84          11 :         assert(s);
      85             : 
      86          11 :         if (s->state != state)
      87          11 :                 bus_unit_send_pending_change_signal(UNIT(s), false);
      88             : 
      89          11 :         old_state = s->state;
      90          11 :         s->state = state;
      91             : 
      92          11 :         if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL))
      93          11 :                 s->timer_event_source = sd_event_source_unref(s->timer_event_source);
      94             : 
      95          11 :         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          11 :         if (state != old_state)
     101          11 :                 log_debug("%s changed %s -> %s", UNIT(s)->id, scope_state_to_string(old_state), scope_state_to_string(state));
     102             : 
     103          11 :         unit_notify(UNIT(s), state_translation_table[old_state], state_translation_table[state], 0);
     104          11 : }
     105             : 
     106          11 : static int scope_add_default_dependencies(Scope *s) {
     107             :         int r;
     108             : 
     109          11 :         assert(s);
     110             : 
     111          11 :         if (!UNIT(s)->default_dependencies)
     112          11 :                 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          11 : static int scope_verify(Scope *s) {
     127          11 :         assert(s);
     128             : 
     129          11 :         if (UNIT(s)->load_state != UNIT_LOADED)
     130           0 :                 return 0;
     131             : 
     132          11 :         if (set_isempty(UNIT(s)->pids) &&
     133          11 :             !MANAGER_IS_RELOADING(UNIT(s)->manager) &&
     134          11 :             !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          11 :         return 0;
     140             : }
     141             : 
     142          11 : static int scope_load_init_scope(Unit *u) {
     143          11 :         assert(u);
     144             : 
     145          11 :         if (!unit_has_name(u, SPECIAL_INIT_SCOPE))
     146           0 :                 return 0;
     147             : 
     148          11 :         u->transient = true;
     149          11 :         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          11 :         u->default_dependencies = false;
     155             : 
     156             :         /* Prettify things, if we can. */
     157          11 :         if (!u->description)
     158          11 :                 u->description = strdup("System and Service Manager");
     159          11 :         if (!u->documentation)
     160          11 :                 (void) strv_extend(&u->documentation, "man:systemd(1)");
     161             : 
     162          11 :         return 1;
     163             : }
     164             : 
     165          11 : static int scope_load(Unit *u) {
     166          11 :         Scope *s = SCOPE(u);
     167             :         int r;
     168             : 
     169          11 :         assert(s);
     170          11 :         assert(u->load_state == UNIT_STUB);
     171             : 
     172          11 :         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          11 :         r = scope_load_init_scope(u);
     177          11 :         if (r < 0)
     178           0 :                 return r;
     179          11 :         r = unit_load_fragment_and_dropin_optional(u);
     180          11 :         if (r < 0)
     181           0 :                 return r;
     182             : 
     183          11 :         if (u->load_state == UNIT_LOADED) {
     184          11 :                 r = unit_patch_contexts(u);
     185          11 :                 if (r < 0)
     186           0 :                         return r;
     187             : 
     188          11 :                 r = unit_set_default_slice(u);
     189          11 :                 if (r < 0)
     190           0 :                         return r;
     191             : 
     192          11 :                 r = scope_add_default_dependencies(s);
     193          11 :                 if (r < 0)
     194           0 :                         return r;
     195             :         }
     196             : 
     197          11 :         return scope_verify(s);
     198             : }
     199             : 
     200          11 : static int scope_coldplug(Unit *u) {
     201          11 :         Scope *s = SCOPE(u);
     202             :         int r;
     203             : 
     204          11 :         assert(s);
     205          11 :         assert(s->state == SCOPE_DEAD);
     206             : 
     207          11 :         if (s->deserialized_state == s->state)
     208           0 :                 return 0;
     209             : 
     210          11 :         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          11 :         if (!IN_SET(s->deserialized_state, SCOPE_DEAD, SCOPE_FAILED))
     217          11 :                 (void) unit_enqueue_rewatch_pids(u);
     218             : 
     219          11 :         bus_scope_track_controller(s);
     220             : 
     221          11 :         scope_set_state(s, s->deserialized_state);
     222          11 :         return 0;
     223             : }
     224             : 
     225           6 : static void scope_dump(Unit *u, FILE *f, const char *prefix) {
     226           6 :         Scope *s = SCOPE(u);
     227             : 
     228           6 :         assert(s);
     229           6 :         assert(f);
     230             : 
     231           6 :         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           6 :         cgroup_context_dump(&s->cgroup_context, f, prefix);
     238           6 :         kill_context_dump(&s->kill_context, f, prefix);
     239           6 : }
     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          87 : _pure_ static UnitActiveState scope_active_state(Unit *u) {
     529          87 :         assert(u);
     530             : 
     531          87 :         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          11 : static void scope_enumerate_perpetual(Manager *m) {
     541             :         Unit *u;
     542             :         int r;
     543             : 
     544          11 :         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          11 :         u = manager_get_unit(m, SPECIAL_INIT_SCOPE);
     552          11 :         if (!u) {
     553          11 :                 r = unit_new_for_name(m, sizeof(Scope), SPECIAL_INIT_SCOPE, &u);
     554          11 :                 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          11 :         u->transient = true;
     561          11 :         u->perpetual = true;
     562          11 :         SCOPE(u)->deserialized_state = SCOPE_RUNNING;
     563             : 
     564          11 :         unit_add_to_load_queue(u);
     565          11 :         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          16 : 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