[systemd-commits] 3 commits - fixme man/systemd.service.xml man/systemd.special.xml.in man/systemd.unit.xml src/dbus-execute.c src/dbus-execute.h src/execute.h src/job.c src/load-fragment.c src/service.c src/socket.c src/systemctl.c src/unit.c src/unit.h units/shutdown.target units/umount.target

Lennart Poettering lennart at kemper.freedesktop.org
Sun Jul 11 18:07:24 PDT 2010


 fixme                      |    6 +++---
 man/systemd.service.xml    |   10 +++++++++-
 man/systemd.special.xml.in |   27 ++++++++++++++++++++++++---
 man/systemd.unit.xml       |   13 +++++++++++++
 src/dbus-execute.c         |    3 ++-
 src/dbus-execute.h         |    4 ++--
 src/execute.h              |    1 +
 src/job.c                  |    9 ++++++---
 src/load-fragment.c        |   25 +++++++++++++++++--------
 src/service.c              |   17 +++++++++++++++--
 src/socket.c               |    8 ++++++--
 src/systemctl.c            |    8 +++++++-
 src/unit.c                 |    6 ++++--
 src/unit.h                 |    3 +++
 units/shutdown.target      |    1 +
 units/umount.target        |    1 +
 16 files changed, 114 insertions(+), 28 deletions(-)

New commits:
commit 3b6fdb5b5afebc49a7e987e3e3bf7aa2615d1671
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 12 02:56:17 2010 +0200

    unit: introduce IgnoreDependencyFailure=

diff --git a/fixme b/fixme
index 7f34510..2c61cff 100644
--- a/fixme
+++ b/fixme
@@ -37,10 +37,10 @@
 
 * systemctl status $PID, systemctl stop $PID!
 
-* make shutdown go on even if conflicting units fail to shut down.
-
 * sulogin in den single user mode, mit plymouth --hide davor
 
+* replace remaining libcgroup use
+
 External:
 
 * patch /etc/init.d/functions with:
diff --git a/man/systemd.special.xml.in b/man/systemd.special.xml.in
index ac9f0f5..64e37d1 100644
--- a/man/systemd.special.xml.in
+++ b/man/systemd.special.xml.in
@@ -84,7 +84,8 @@
                 <filename>systemd-initctl.service</filename>,
                 <filename>systemd-initctl.socket</filename>,
                 <filename>systemd-logger.service</filename>,
-                <filename>systemd-logger.socket</filename></para>
+                <filename>systemd-logger.socket</filename>,
+                <filename>umount.target</filename></para>
         </refsynopsisdiv>
 
         <refsect1>
@@ -499,8 +500,10 @@
                                         terminated on system shutdown
                                         shall add Conflicts
                                         dependencies to this unit for
-                                        their service unit during
-                                        installation.</para>
+                                        their service unit, which is
+                                        implicitly done when
+                                        <varname>DefaultDependencies=yes</varname>
+                                        is set (the default).</para>
 
                                         <para>systemd automatically
                                         adds dependencies of type
@@ -653,6 +656,24 @@
                                         kernel log buffer.</para>
                                 </listitem>
                         </varlistentry>
+                        <varlistentry>
+                                <term><filename>umount.target</filename></term>
+                                <listitem>
+                                        <para>A special target unit
+                                        that umounts all mount and
+                                        automount points on system
+                                        shutdown.</para>
+
+                                        <para>Mounts that shall be
+                                        unmounted on system shutdown
+                                        shall add Conflicts
+                                        dependencies to this unit for
+                                        their mount unit, which is
+                                        implicitly done when
+                                        <varname>DefaultDependencies=yes</varname>
+                                        is set (the default).</para>
+                                </listitem>
+                        </varlistentry>
                 </variablelist>
         </refsect1>
 
diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml
index 5541304..a03df65 100644
--- a/man/systemd.unit.xml
+++ b/man/systemd.unit.xml
@@ -482,6 +482,19 @@
                                 ones.</para></listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term><varname>IgnoreDependencyFailure=</varname></term>
+
+                                <listitem><para>Takes a boolean
+                                argument. If <option>true</option> and
+                                a requirement dependency of this unit
+                                fails to start up this unit will be
+                                started nonetheless, ignoring that
+                                failure. If <option>false</option>
+                                (the default) and a dependency unit
+                                fails the unit will immediately fail
+                                too and the job is removed.</para></listitem>
+                        </varlistentry>
                 </variablelist>
 
                 <para>Unit file may include a [Install] section, which
diff --git a/src/job.c b/src/job.c
index 7cbde80..8cc9d74 100644
--- a/src/job.c
+++ b/src/job.c
@@ -495,14 +495,16 @@ int job_finish_and_invalidate(Job *j, bool success) {
                     t == JOB_RELOAD_OR_START) {
 
                         SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY], i)
-                                if (other->meta.job &&
+                                if (!other->meta.ignore_dependency_failure &&
+                                    other->meta.job &&
                                     (other->meta.job->type == JOB_START ||
                                      other->meta.job->type == JOB_VERIFY_ACTIVE ||
                                      other->meta.job->type == JOB_RELOAD_OR_START))
                                         job_finish_and_invalidate(other->meta.job, false);
 
                         SET_FOREACH(other, u->meta.dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
-                                if (other->meta.job &&
+                                if (!other->meta.ignore_dependency_failure &&
+                                    other->meta.job &&
                                     !other->meta.job->override &&
                                     (other->meta.job->type == JOB_START ||
                                      other->meta.job->type == JOB_VERIFY_ACTIVE ||
@@ -512,7 +514,8 @@ int job_finish_and_invalidate(Job *j, bool success) {
                 } else if (t == JOB_STOP) {
 
                         SET_FOREACH(other, u->meta.dependencies[UNIT_CONFLICTS], i)
-                                if (other->meta.job &&
+                                if (!other->meta.ignore_dependency_failure &&
+                                    other->meta.job &&
                                     (other->meta.job->type == JOB_START ||
                                      other->meta.job->type == JOB_VERIFY_ACTIVE ||
                                      other->meta.job->type == JOB_RELOAD_OR_START))
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 1d40b69..8e4ec74 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -1562,6 +1562,7 @@ static int load_from_path(Unit *u, const char *path) {
                 { "StopWhenUnneeded",       config_parse_bool,            &u->meta.stop_when_unneeded,                     "Unit"    },
                 { "OnlyByDependency",       config_parse_bool,            &u->meta.only_by_dependency,                     "Unit"    },
                 { "DefaultDependencies",    config_parse_bool,            &u->meta.default_dependencies,                   "Unit"    },
+                { "IgnoreDependencyFailure",config_parse_bool,            &u->meta.ignore_dependency_failure,              "Unit"    },
 
                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },
                 { "ExecStartPre",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_PRE,  "Service" },
diff --git a/src/unit.c b/src/unit.c
index b362fd3..66372f2 100644
--- a/src/unit.c
+++ b/src/unit.c
@@ -626,11 +626,13 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) {
                         "%s\tRecursive Stop: %s\n"
                         "%s\tStopWhenUnneeded: %s\n"
                         "%s\tOnlyByDependency: %s\n"
-                        "%s\tDefaultDependencies: %s\n",
+                        "%s\tDefaultDependencies: %s\n"
+                        "%s\tIgnoreDependencyFailure: %s\n",
                         prefix, yes_no(u->meta.recursive_stop),
                         prefix, yes_no(u->meta.stop_when_unneeded),
                         prefix, yes_no(u->meta.only_by_dependency),
-                        prefix, yes_no(u->meta.default_dependencies));
+                        prefix, yes_no(u->meta.default_dependencies),
+                        prefix, yes_no(u->meta.ignore_dependency_failure));
 
                 LIST_FOREACH(by_unit, b, u->meta.cgroup_bondings)
                         fprintf(f, "%s\tControlGroup: %s:%s\n",
diff --git a/src/unit.h b/src/unit.h
index c9fd4a5..3f4bbd9 100644
--- a/src/unit.h
+++ b/src/unit.h
@@ -184,6 +184,9 @@ struct Meta {
         /* Create default depedencies */
         bool default_dependencies;
 
+        /* Bring up this unit even if a dependency fails to start */
+        bool ignore_dependency_failure;
+
         /* When deserializing, temporarily store the job type for this
          * unit here, if there was a job scheduled */
         int deserialized_job; /* This is actually of type JobType */
diff --git a/units/shutdown.target b/units/shutdown.target
index c05b8b9..586ca4a 100644
--- a/units/shutdown.target
+++ b/units/shutdown.target
@@ -10,3 +10,4 @@
 [Unit]
 Description=Shutdown
 OnlyByDependency=yes
+IgnoreDependencyFailure=yes
diff --git a/units/umount.target b/units/umount.target
index a5f31e0..6a00c31 100644
--- a/units/umount.target
+++ b/units/umount.target
@@ -10,3 +10,4 @@
 [Unit]
 Description=Unmount All Filesystems
 OnlyByDependency=yes
+IgnoreDependencyFailure=yes
commit f6023656e10823dff9e4b9f70628b671b3f4ed96
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 12 02:31:40 2010 +0200

    service: trim cgroups if services that are "active" but "exited"

diff --git a/src/service.c b/src/service.c
index f8b4ff6..4710850 100644
--- a/src/service.c
+++ b/src/service.c
@@ -1179,6 +1179,11 @@ static void service_set_state(Service *s, ServiceState state) {
                 service_connection_unref(s);
         }
 
+        /* For the inactive states unit_notify() will trim the cgroup,
+         * but for exit we have to do that ourselves... */
+        if (state == SERVICE_EXITED)
+                cgroup_bonding_trim_list(s->meta.cgroup_bondings, true);
+
         if (old_state != state)
                 log_debug("%s changed %s -> %s", s->meta.id, service_state_to_string(old_state), service_state_to_string(state));
 
commit b708e7cea941538bfd5e20ce0a723c19b7da7d1d
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jul 12 02:25:42 2010 +0200

    execute: optionally ignore return status of invoked commands

diff --git a/fixme b/fixme
index abdbaf6..7f34510 100644
--- a/fixme
+++ b/fixme
@@ -35,11 +35,11 @@
 
 * selinux
 
-* Show exit status auf auxiliary programs in systemctl status
+* systemctl status $PID, systemctl stop $PID!
 
-* rtkit status
+* make shutdown go on even if conflicting units fail to shut down.
 
-* systemctl status $PID, systemctl stop $PID!
+* sulogin in den single user mode, mit plymouth --hide davor
 
 External:
 
diff --git a/man/systemd.service.xml b/man/systemd.service.xml
index 709a448..9623883 100644
--- a/man/systemd.service.xml
+++ b/man/systemd.service.xml
@@ -256,7 +256,15 @@
                                 token will be passed as
                                 <literal>argv[0]</literal> to the
                                 executed process, followed by the
-                                further arguments specified. Unless
+                                further arguments specified. If the
+                                first token is prefixed with
+                                <literal>-</literal> an error code of
+                                the command normally considered a
+                                failure is ignored and considered
+                                success. If both <literal>-</literal>
+                                and <literal>@</literal> are used for
+                                the same command the latter must
+                                preceed the latter. Unless
                                 <varname>Type=forking</varname> is
                                 set, the process started via this
                                 command line will be considered the
diff --git a/src/dbus-execute.c b/src/dbus-execute.c
index 1ef6f25..bb660b1 100644
--- a/src/dbus-execute.c
+++ b/src/dbus-execute.c
@@ -258,7 +258,7 @@ int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *prope
         assert(i);
         assert(property);
 
-        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasttuii)", &sub))
+        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttuii)", &sub))
                 return -ENOMEM;
 
         LIST_FOREACH(command, c, c) {
@@ -283,6 +283,7 @@ int bus_execute_append_command(Manager *m, DBusMessageIter *i, const char *prope
                 status = (int32_t) c->exec_status.status;
 
                 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
+                    !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &c->ignore) ||
                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
                     !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &c->exec_status.pid) ||
diff --git a/src/dbus-execute.h b/src/dbus-execute.h
index 85c390b..6cd88d4 100644
--- a/src/dbus-execute.h
+++ b/src/dbus-execute.h
@@ -88,7 +88,7 @@
         "  <property name=\"KillSignal\" type=\"i\" access=\"read\"/>\n"
 
 #define BUS_EXEC_COMMAND_INTERFACE(name)                             \
-        "  <property name=\"" name "\" type=\"a(sasttuii)\" access=\"read\"/>\n"
+        "  <property name=\"" name "\" type=\"a(sasbttuii)\" access=\"read\"/>\n"
 
 #define BUS_EXEC_CONTEXT_PROPERTIES(interface, context)                 \
         { interface, "Environment",                   bus_property_append_strv,   "as",    (context).environment                   }, \
@@ -152,7 +152,7 @@
         { interface, prefix "Status",                 bus_property_append_int,    "i",     &(estatus).status                       }
 
 #define BUS_EXEC_COMMAND_PROPERTY(interface, command, name)             \
-        { interface, name, bus_execute_append_command, "a(sasttuii)", (command) }
+        { interface, name, bus_execute_append_command, "a(sasbttuii)", (command) }
 
 int bus_execute_append_output(Manager *m, DBusMessageIter *i, const char *property, void *data);
 int bus_execute_append_input(Manager *m, DBusMessageIter *i, const char *property, void *data);
diff --git a/src/execute.h b/src/execute.h
index f93ab7a..4b3449e 100644
--- a/src/execute.h
+++ b/src/execute.h
@@ -87,6 +87,7 @@ struct ExecCommand {
         char *path;
         char **argv;
         ExecStatus exec_status;
+        bool ignore;
         LIST_FIELDS(ExecCommand, command); /* useful for chaining commands */
 };
 
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 394aa02..1d40b69 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -382,7 +382,7 @@ static int config_parse_exec(
                 char *w;
                 size_t l;
                 char *state;
-                bool honour_argv0, write_to_path;
+                bool honour_argv0 = false, ignore = false;
 
                 path = NULL;
                 nce = NULL;
@@ -393,9 +393,17 @@ static int config_parse_exec(
                 if (rvalue[0] == 0)
                         break;
 
-                honour_argv0 = rvalue[0] == '@';
+                if (rvalue[0] == '-') {
+                        ignore = true;
+                        rvalue ++;
+                }
+
+                if (rvalue[0] == '@') {
+                        honour_argv0 = true;
+                        rvalue ++;
+                }
 
-                if (rvalue[honour_argv0 ? 1 : 0] != '/') {
+                if (*rvalue != '/') {
                         log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
                         return -EINVAL;
                 }
@@ -408,19 +416,18 @@ static int config_parse_exec(
                         k++;
                 }
 
-                if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
+                if (!(n = new(char*, k + !honour_argv0)))
                         return -ENOMEM;
 
                 k = 0;
-                write_to_path = honour_argv0;
                 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
                         if (strncmp(w, ";", l) == 0)
                                 break;
 
-                        if (write_to_path) {
-                                if (!(path = cunescape_length(w+1, l-1)))
+                        if (honour_argv0 && w == rvalue) {
+                                assert(!path);
+                                if (!(path = cunescape_length(w, l)))
                                         goto fail;
-                                write_to_path = false;
                         } else {
                                 if (!(n[k++] = cunescape_length(w, l)))
                                         goto fail;
@@ -446,6 +453,7 @@ static int config_parse_exec(
 
                 nce->argv = n;
                 nce->path = path;
+                nce->ignore = ignore;
 
                 path_kill_slashes(nce->path);
 
diff --git a/src/service.c b/src/service.c
index 481c044..f8b4ff6 100644
--- a/src/service.c
+++ b/src/service.c
@@ -2171,7 +2171,6 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         assert(pid >= 0);
 
         success = is_clean_exit(code, status);
-        s->failure = s->failure || !success;
 
         if (s->main_pid == pid) {
 
@@ -2181,9 +2180,13 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
                 if (s->type != SERVICE_FORKING) {
                         assert(s->exec_command[SERVICE_EXEC_START]);
                         s->exec_command[SERVICE_EXEC_START]->exec_status = s->main_exec_status;
+
+                        if (s->exec_command[SERVICE_EXEC_START]->ignore)
+                                success = true;
                 }
 
                 log_debug("%s: main process exited, code=%s, status=%i", u->meta.id, sigchld_code_to_string(code), status);
+                s->failure = s->failure || !success;
 
                 /* The service exited, so the service is officially
                  * gone. */
@@ -2230,12 +2233,17 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
 
         } else if (s->control_pid == pid) {
 
-                if (s->control_command)
+                if (s->control_command) {
                         exec_status_exit(&s->control_command->exec_status, pid, code, status);
 
+                        if (s->control_command->ignore)
+                                success = true;
+                }
+
                 s->control_pid = 0;
 
                 log_debug("%s: control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
+                s->failure = s->failure || !success;
 
                 /* If we are shutting things down anyway we
                  * don't care about failing commands. */
diff --git a/src/socket.c b/src/socket.c
index 7ff2927..2d113ae 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -1400,12 +1400,16 @@ static void socket_sigchld_event(Unit *u, pid_t pid, int code, int status) {
         s->control_pid = 0;
 
         success = is_clean_exit(code, status);
-        s->failure = s->failure || !success;
 
-        if (s->control_command)
+        if (s->control_command) {
                 exec_status_exit(&s->control_command->exec_status, pid, code, status);
 
+                if (s->control_command->ignore)
+                        success = true;
+        }
+
         log_debug("%s control process exited, code=%s status=%i", u->meta.id, sigchld_code_to_string(code), status);
+        s->failure = s->failure || !success;
 
         if (s->control_command && s->control_command->command_next && success) {
                 log_debug("%s running next command for state %s", u->meta.id, socket_state_to_string(s->state));
diff --git a/src/systemctl.c b/src/systemctl.c
index d1892e4..45e900c 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -933,6 +933,8 @@ typedef struct ExecStatusInfo {
         char *path;
         char **argv;
 
+        bool ignore;
+
         usec_t start_timestamp;
         usec_t exit_timestamp;
         pid_t pid;
@@ -957,6 +959,7 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
         unsigned n;
         uint32_t pid;
         int32_t code, status;
+        dbus_bool_t ignore;
 
         assert(i);
         assert(i);
@@ -1002,6 +1005,7 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
         }
 
         if (!dbus_message_iter_next(&sub2) ||
+            bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, true) < 0 ||
             bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_timestamp, true) < 0 ||
             bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_timestamp, true) < 0 ||
             bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) < 0 ||
@@ -1009,6 +1013,7 @@ static int exec_status_info_deserialize(DBusMessageIter *sub, ExecStatusInfo *i)
             bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) < 0)
                 return -EIO;
 
+        i->ignore = ignore;
         i->start_timestamp = (usec_t) start_timestamp;
         i->exit_timestamp = (usec_t) exit_timestamp;
         i->pid = (pid_t) pid;
@@ -1535,10 +1540,11 @@ static int print_property(const char *name, DBusMessageIter *iter) {
 
                                         t = strv_join(info.argv, " ");
 
-                                        printf("%s={ path=%s ; argv[]=%s;  start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
+                                        printf("%s={ path=%s ; argv[]=%s ; ignore=%s ; start_time=[%s] ; stop_time=[%s] ; pid=%u ; code=%s ; status=%i%s%s }\n",
                                                name,
                                                strna(info.path),
                                                strna(t),
+                                               yes_no(info.ignore),
                                                strna(format_timestamp(timestamp1, sizeof(timestamp1), info.start_timestamp)),
                                                strna(format_timestamp(timestamp2, sizeof(timestamp2), info.exit_timestamp)),
                                                (unsigned) info. pid,


More information about the systemd-commits mailing list