]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Revert "Introduce ExitType"
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 30 Jun 2021 12:21:33 +0000 (14:21 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 30 Jun 2021 19:56:47 +0000 (21:56 +0200)
This reverts commit cb0e818f7cc2499d81ef143e5acaa00c6e684711.

After this was merged, some design and implementation issues were discovered,
see the discussion in #18782 and #19385. They certainly can be fixed, but so
far nobody has stepped up, and we're nearing a release. Hopefully, this feature
can be merged again after a rework.

Fixes #19345.

19 files changed:
NEWS
docs/TRANSIENT-SETTINGS.md
man/org.freedesktop.systemd1.xml
man/systemd.service.xml
shell-completion/bash/systemd-run
shell-completion/zsh/_systemd-run
src/core/dbus-service.c
src/core/load-fragment-gperf.gperf.in
src/core/load-fragment.c
src/core/load-fragment.h
src/core/service.c
src/core/service.h
src/shared/bus-unit-util.c
src/xdg-autostart-generator/xdg-autostart-service.c
test/TEST-56-EXIT-TYPE/Makefile [deleted symlink]
test/TEST-56-EXIT-TYPE/test.sh [deleted file]
test/fuzz/fuzz-unit-file/directives.service
test/units/testsuite-56.service [deleted file]
test/units/testsuite-56.sh [deleted file]

diff --git a/NEWS b/NEWS
index 814e3e47e9021474a29f60b5e201121a03d74301..d7ba481fe1b1289266059f563100aa0586c628b7 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -34,13 +34,6 @@ CHANGES WITH 249 in spe:
           previously unprovisioned images (i.e. images with a mostly empty
           /etc/).
 
-        * Services gained a new ExitType= setting which can configure how to
-          determine when a service exited: the default is "main" which defines
-          the runtime by the service's main process lifetime (this matches the
-          only behaviour implemented in v248 and before), but with "cgroup" the
-          runtime is defined by the existence of any process in the service's
-          cgroup.
-
         * The systemd-machine-id-setup tool now supports a --image= switch for
           provisioning a machine ID file into an OS disk image, similar to how
           --root= operates on an OS file tree. This matches the existing switch
index 070ad5a2859ae50a13054561d0a72217c20cdda6..3a75627ca990db9020856a5410a115ddecdb7415 100644 (file)
@@ -304,7 +304,6 @@ Most service unit settings are available for transient units.
 ✓ ExecStartPre=
 ✓ ExecStop=
 ✓ ExecStopPost=
-✓ ExitType=
 ✓ FileDescriptorStoreMax=
 ✓ GuessMainPID=
 ✓ NonBlocking=
index 8249e31d07a61c48b3fab138a70afe7f568dc174..74a920273afbbf9b64a818215c6e8592505c0ba1 100644 (file)
@@ -2298,8 +2298,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s Type = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
-      readonly s ExitType = '...';
-      @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s Restart = '...';
       @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
       readonly s PIDFile = '...';
@@ -2866,8 +2864,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <!--property Type is not documented!-->
 
-    <!--property ExitType is not documented!-->
-
     <!--property Restart is not documented!-->
 
     <!--property PIDFile is not documented!-->
@@ -3386,8 +3382,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
 
     <variablelist class="dbus-property" generated="True" extra-ref="Type"/>
 
-    <variablelist class="dbus-property" generated="True" extra-ref="ExitType"/>
-
     <variablelist class="dbus-property" generated="True" extra-ref="Restart"/>
 
     <variablelist class="dbus-property" generated="True" extra-ref="PIDFile"/>
index 50d1a1d85d638f2404c2b943df6226bb48924a76..350bc5f8e5bca5054c2702ed046ab9bfbe2d65f4 100644 (file)
         </listitem>
       </varlistentry>
 
-      <varlistentry>
-        <term><varname>ExitType=</varname></term>
-
-        <listitem>
-          <para>Configures the process exit type for this service unit. One of <option>main</option> or
-          <option>cgroup</option>:</para>
-
-          <itemizedlist>
-            <listitem><para>If set to <option>main</option> (the default), the service manager
-            will consider the unit stopped when the main process, which is determined according to the `Type`, exits.
-            </para></listitem>
-
-            <listitem><para>The <option>cgroup</option> exit type is meant for applications whose forking model is not
-            known ahead of time and which might not have a specific main process. The service will stay running as long
-            as at least one process in the cgroup is running. The exit status of the service is that of the last
-            process in the cgroup to exit.</para></listitem>
-          </itemizedlist>
-
-          <para>It is generally recommended to use <varname>ExitType=</varname><option>main</option> when a service has
-          a known forking model and a main process can reliably be determined. <varname>ExitType=</varname>
-          <option>cgroup</option> is well suited for transient or automatically generated services, such as graphical
-          applications inside of a desktop environment.</para>
-        </listitem>
-      </varlistentry>
-
       <varlistentry>
         <term><varname>RemainAfterExit=</varname></term>
 
index c5db8b77bd8f3dbee88a07494fdd47a8360e2ff0..76b9700f79fd5e8dd0dbc4d7cee1459810e52eae 100644 (file)
@@ -78,7 +78,7 @@ _systemd_run() {
         -p|--property)
             local comps='CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP=
                          SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group=
-                         DevicePolicy= KillMode= ExitType= DeviceAllow= BlockIOReadBandwidth=
+                         DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth=
                          BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment=
                          KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA=
                          LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC=
index 322bb60e1cacc8e5306429716d33e766195e21ab..cd0ad8245f7579b4db928ac4bfdc0843af69c3f8 100644 (file)
@@ -45,7 +45,7 @@ _arguments \
     {-p+,--property=}'[Set unit property]:NAME=VALUE:(( \
                 CPUAccounting= MemoryAccounting= BlockIOAccounting= SendSIGHUP= \
                 SendSIGKILL= MemoryLimit= CPUShares= BlockIOWeight= User= Group= \
-                DevicePolicy= KillMode= ExitType= DeviceAllow= BlockIOReadBandwidth= \
+                DevicePolicy= KillMode= DeviceAllow= BlockIOReadBandwidth= \
                 BlockIOWriteBandwidth= BlockIODeviceWeight= Nice= Environment= \
                 KillSignal= RestartKillSignal= FinalKillSignal= LimitCPU= LimitFSIZE= LimitDATA= \
                 LimitSTACK= LimitCORE= LimitRSS= LimitNOFILE= LimitAS= LimitNPROC= \
index 13d555041e5a354c122acfae16da53b1d0d5de60..02628cd39eab1f97f6b5367b83c92662a937a130 100644 (file)
@@ -27,7 +27,6 @@
 #include "unit.h"
 
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
-static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exit_type, service_exit_type, ServiceExitType);
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
@@ -193,7 +192,6 @@ int bus_service_method_mount_image(sd_bus_message *message, void *userdata, sd_b
 const sd_bus_vtable bus_service_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
-        SD_BUS_PROPERTY("ExitType", "s", property_get_exit_type, offsetof(Service, exit_type), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -379,7 +377,6 @@ static int bus_set_transient_std_fd(
 }
 static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access_from_string);
 static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string);
-static BUS_DEFINE_SET_TRANSIENT_PARSE(service_exit_type, ServiceExitType, service_exit_type_from_string);
 static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string);
 static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
 static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
@@ -417,9 +414,6 @@ static int bus_service_set_transient_property(
         if (streq(name, "Type"))
                 return bus_set_transient_service_type(u, name, &s->type, message, flags, error);
 
-        if (streq(name, "ExitType"))
-                return bus_set_transient_service_exit_type(u, name, &s->exit_type, message, flags, error);
-
         if (streq(name, "OOMPolicy"))
                 return bus_set_transient_oom_policy(u, name, &s->oom_policy, message, flags, error);
 
index d343145fa99ac5a084ac9f100770d1346858a122..42441eab6ef59d4d3d31e182f3c02506cea1887f 100644 (file)
@@ -383,7 +383,6 @@ Service.StartLimitAction,                config_parse_emergency_action,
 Service.FailureAction,                   config_parse_emergency_action,               0,                                  offsetof(Unit, failure_action)
 Service.RebootArgument,                  config_parse_unit_string_printf,             0,                                  offsetof(Unit, reboot_arg)
 Service.Type,                            config_parse_service_type,                   0,                                  offsetof(Service, type)
-Service.ExitType,                        config_parse_service_exit_type,              0,                                  offsetof(Service, exit_type)
 Service.Restart,                         config_parse_service_restart,                0,                                  offsetof(Service, restart)
 Service.PermissionsStartOnly,            config_parse_bool,                           0,                                  offsetof(Service, permissions_start_only)
 Service.RootDirectoryStartOnly,          config_parse_bool,                           0,                                  offsetof(Service, root_directory_start_only)
index 6bb614316313cb0790ab7762e86599ceed473ab1..8fb3c378ee4e4ac6a1f01fded44e200b64443b87 100644 (file)
@@ -135,7 +135,6 @@ DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_home, protect_home, ProtectHome, "
 DEFINE_CONFIG_PARSE_ENUM(config_parse_protect_system, protect_system, ProtectSystem, "Failed to parse protect system value");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
-DEFINE_CONFIG_PARSE_ENUM(config_parse_service_exit_type, service_exit_type, ServiceExitType, "Failed to parse service exit type");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_timeout_failure_mode, service_timeout_failure_mode, ServiceTimeoutFailureMode, "Failed to parse timeout failure mode");
 DEFINE_CONFIG_PARSE_ENUM(config_parse_socket_bind, socket_address_bind_ipv6_only_or_bool, SocketAddressBindIPv6Only, "Failed to parse bind IPv6 only value");
@@ -5845,7 +5844,6 @@ void unit_dump_config_items(FILE *f) {
                 { config_parse_unit_deps,             "UNIT [...]" },
                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
                 { config_parse_service_type,          "SERVICETYPE" },
-                { config_parse_service_exit_type,     "SERVICEEXITTYPE" },
                 { config_parse_service_restart,       "SERVICERESTART" },
                 { config_parse_service_timeout_failure_mode, "TIMEOUTMODE" },
                 { config_parse_kill_mode,             "KILLMODE" },
index d722041f962363981cd2fd397e71f05d17b4b03f..45e9c397e4e1f0eca338221643f7cfceadfca5c6 100644 (file)
@@ -32,7 +32,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_abort);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_timeout_failure_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_type);
-CONFIG_PARSER_PROTOTYPE(config_parse_service_exit_type);
 CONFIG_PARSER_PROTOTYPE(config_parse_service_restart);
 CONFIG_PARSER_PROTOTYPE(config_parse_socket_bindtodevice);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_output);
index af5a2decf11347456a6087102976161ce0194b48..c6e667b5de88b772343cc6d062e093137bbcfb0e 100644 (file)
@@ -1621,25 +1621,18 @@ static int control_pid_good(Service *s) {
         return s->control_pid > 0;
 }
 
-static int cgroup_empty(Service *s) {
-        assert(s);
-
-        /* Returns 0 if there is no cgroup, > 0 if is empty or doesn't exist, < 0 if we can't figure it out */
-
-        if (!UNIT(s)->cgroup_path)
-                return 0;
-
-        return cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
-}
-
-
 static int cgroup_good(Service *s) {
         int r;
 
+        assert(s);
+
         /* Returns 0 if the cgroup is empty or doesn't exist, > 0 if it is exists and is populated, < 0 if we can't
          * figure it out */
 
-        r = cgroup_empty(s);
+        if (!UNIT(s)->cgroup_path)
+                return 0;
+
+        r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, UNIT(s)->cgroup_path);
         if (r < 0)
                 return r;
 
@@ -3402,14 +3395,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         else
                 assert_not_reached("Unknown code");
 
-        /* Services with ExitType=cgroup ignore the main PID for purposes of exit status */
-        if (s->exit_type == SERVICE_EXIT_CGROUP && s->main_pid == pid) {
-                service_unwatch_main_pid(s);
-                s->main_pid_known = false;
-        }
-
-        if ((s->exit_type == SERVICE_EXIT_MAIN && s->main_pid == pid) ||
-            (s->exit_type == SERVICE_EXIT_CGROUP && cgroup_empty(s) && !control_pid_good(s))) {
+        if (s->main_pid == pid) {
                 /* Forking services may occasionally move to a new PID.
                  * As long as they update the PID file before exiting the old
                  * PID, they're fine. */
@@ -3442,7 +3428,7 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
                 unit_log_process_exit(
                                 u,
-                                s->exit_type == SERVICE_EXIT_CGROUP ? "Last process" : "Main process",
+                                "Main process",
                                 service_exec_command_to_string(SERVICE_EXEC_START),
                                 f == SERVICE_SUCCESS,
                                 code, status);
@@ -4465,13 +4451,6 @@ static const char* const service_type_table[_SERVICE_TYPE_MAX] = {
 
 DEFINE_STRING_TABLE_LOOKUP(service_type, ServiceType);
 
-static const char* const service_exit_type_table[_SERVICE_EXIT_TYPE_MAX] = {
-        [SERVICE_EXIT_MAIN] = "main",
-        [SERVICE_EXIT_CGROUP] = "cgroup",
-};
-
-DEFINE_STRING_TABLE_LOOKUP(service_exit_type, ServiceExitType);
-
 static const char* const service_exec_command_table[_SERVICE_EXEC_COMMAND_MAX] = {
         [SERVICE_EXEC_CONDITION] = "ExecCondition",
         [SERVICE_EXEC_START_PRE] = "ExecStartPre",
index 0d51fc31535acabcf919799ef999b068ef18aa25..6d931c3d5e4aeb86bfb39de3099104d662364398 100644 (file)
@@ -35,13 +35,6 @@ typedef enum ServiceType {
         _SERVICE_TYPE_INVALID = -EINVAL,
 } ServiceType;
 
-typedef enum ServiceExitType {
-        SERVICE_EXIT_MAIN,    /* we consider the main PID when deciding if the service exited */
-        SERVICE_EXIT_CGROUP,  /* we wait for the last process in the cgroup to exit */
-        _SERVICE_EXIT_TYPE_MAX,
-        _SERVICE_EXIT_TYPE_INVALID = -EINVAL,
-} ServiceExitType;
-
 typedef enum ServiceExecCommand {
         SERVICE_EXEC_CONDITION,
         SERVICE_EXEC_START_PRE,
@@ -104,7 +97,6 @@ struct Service {
         Unit meta;
 
         ServiceType type;
-        ServiceExitType exit_type;
         ServiceRestart restart;
         ExitStatusSet restart_prevent_status;
         ExitStatusSet restart_force_status;
@@ -234,9 +226,6 @@ ServiceRestart service_restart_from_string(const char *s) _pure_;
 const char* service_type_to_string(ServiceType i) _const_;
 ServiceType service_type_from_string(const char *s) _pure_;
 
-const char* service_exit_type_to_string(ServiceExitType i) _const_;
-ServiceExitType service_exit_type_from_string(const char *s) _pure_;
-
 const char* service_exec_command_to_string(ServiceExecCommand i) _const_;
 ServiceExecCommand service_exec_command_from_string(const char *s) _pure_;
 
index 31a6c63f0c999904687699dabccaa9802c83a037..d3a5b25d186bf67e5a5f4d39ec9c5c9ee8cf0d60 100644 (file)
@@ -1992,7 +1992,6 @@ static int bus_append_service_property(sd_bus_message *m, const char *field, con
 
         if (STR_IN_SET(field, "PIDFile",
                               "Type",
-                              "ExitType",
                               "Restart",
                               "BusName",
                               "NotifyAccess",
index 5068c0ebb39da4e46b64aa2e320538dd7fa2edc3..fe73bfe9db32864dea93f9cfd22c92b8271698ba 100644 (file)
@@ -598,7 +598,6 @@ int xdg_autostart_service_generate_unit(
         fprintf(f,
                 "\n[Service]\n"
                 "Type=exec\n"
-                "ExitType=cgroup\n"
                 "ExecStart=:%s\n"
                 "Restart=no\n"
                 "TimeoutSec=5s\n"
diff --git a/test/TEST-56-EXIT-TYPE/Makefile b/test/TEST-56-EXIT-TYPE/Makefile
deleted file mode 120000 (symlink)
index e9f93b1..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../TEST-01-BASIC/Makefile
\ No newline at end of file
diff --git a/test/TEST-56-EXIT-TYPE/test.sh b/test/TEST-56-EXIT-TYPE/test.sh
deleted file mode 100755 (executable)
index 0f84dca..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/usr/bin/env bash
-set -e
-
-TEST_DESCRIPTION="test ExitType=cgroup"
-
-# shellcheck source=test/test-functions
-. "${TEST_BASE_DIR:?}/test-functions"
-
-do_test "$@"
index b5df300a6bcf536ef69437fc7a0214f2bed44c34..de7d2c7dafeaa5e5887a0ae8d70fe42759f8d841 100644 (file)
@@ -160,7 +160,6 @@ ExecStartPost=
 ExecStartPre=
 ExecStop=
 ExecStopPost=
-ExitType=
 ExtensionImages=
 FailureAction=
 FileDescriptorStoreMax=
diff --git a/test/units/testsuite-56.service b/test/units/testsuite-56.service
deleted file mode 100644 (file)
index d8ad589..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-[Unit]
-Description=TEST-56-EXIT-TYPE
-
-[Service]
-ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh
-Type=oneshot
diff --git a/test/units/testsuite-56.sh b/test/units/testsuite-56.sh
deleted file mode 100755 (executable)
index 27bd3ca..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/usr/bin/env bash
-set -eux
-
-systemd-analyze log-level debug
-
-# Multiple level process tree, parent process stays up
-cat >/tmp/test56-exit-cgroup.sh <<EOF
-#!/usr/bin/env bash
-set -eux
-
-# process tree: systemd -> sleep
-sleep infinity &
-disown
-
-# process tree: systemd -> bash -> bash -> sleep
-((sleep infinity); true) &
-
-# process tree: systemd -> bash -> sleep
-sleep infinity
-EOF
-chmod +x /tmp/test56-exit-cgroup.sh
-
-# service should be stopped cleanly
-(sleep 1; systemctl stop one) &
-systemd-run --wait --unit=one -p ExitType=cgroup /tmp/test56-exit-cgroup.sh
-
-# same thing with a truthy exec condition
-(sleep 1; systemctl stop two) &
-systemd-run --wait --unit=two -p ExitType=cgroup -p ExecCondition=true /tmp/test56-exit-cgroup.sh
-
-# false exec condition: systemd-run should exit immediately with status code: 1
-systemd-run --wait --unit=three -p ExitType=cgroup -p ExecCondition=false /tmp/test56-exit-cgroup.sh \
-    && { echo 'unexpected success'; exit 1; }
-
-# service should exit uncleanly
-(sleep 1; systemctl kill --signal 9 four) &
-systemd-run --wait --unit=four -p ExitType=cgroup /tmp/test56-exit-cgroup.sh \
-    && { echo 'unexpected success'; exit 1; }
-
-
-# Multiple level process tree, parent process exits quickly
-cat >/tmp/test56-exit-cgroup-parentless.sh <<EOF
-#!/usr/bin/env bash
-set -eux
-
-# process tree: systemd -> sleep
-sleep infinity &
-
-# process tree: systemd -> bash -> sleep
-((sleep infinity); true) &
-EOF
-chmod +x /tmp/test56-exit-cgroup-parentless.sh
-
-# service should be stopped cleanly
-(sleep 1; systemctl stop five) &
-systemd-run --wait --unit=five -p ExitType=cgroup /tmp/test56-exit-cgroup-parentless.sh
-
-# service should exit uncleanly
-(sleep 1; systemctl kill --signal 9 six) &
-systemd-run --wait --unit=six -p ExitType=cgroup /tmp/test56-exit-cgroup-parentless.sh \
-    && { echo 'unexpected success'; exit 1; }
-
-
-# Multiple level process tree, parent process exits uncleanly but last process exits cleanly
-cat >/tmp/test56-exit-cgroup-clean.sh <<EOF
-#!/usr/bin/env bash
-set -eux
-
-# process tree: systemd -> bash -> sleep
-(sleep 1; true) &
-
-exit 255
-EOF
-chmod +x /tmp/test56-exit-cgroup-clean.sh
-
-# service should exit cleanly and be garbage-collected
-systemd-run --wait --unit=seven -p ExitType=cgroup /tmp/test56-exit-cgroup-clean.sh
-
-
-# Multiple level process tree, parent process exits cleanly but last process exits uncleanly
-cat >/tmp/test56-exit-cgroup-unclean.sh <<EOF
-#!/usr/bin/env bash
-set -eux
-
-# process tree: systemd -> bash -> sleep
-(sleep 1; exit 255) &
-EOF
-chmod +x /tmp/test56-exit-cgroup-unclean.sh
-
-# service should exit uncleanly after 1 second
-systemd-run --wait --unit=eight -p ExitType=cgroup /tmp/test56-exit-cgroup-unclean.sh \
-    && { echo 'unexpected success'; exit 1; }
-
-systemd-analyze log-level info
-
-echo OK >/testok
-
-exit 0