service/systemctl: don't consider LSB exit codes 5 and 6 as failure, and decode exit codes in systemctl

This commit is contained in:
Lennart Poettering 2010-08-19 03:18:49 +02:00
parent 8a2b3c097b
commit d06dacd002
9 changed files with 47 additions and 172 deletions

View File

@ -299,6 +299,7 @@ libsystemd_core_la_SOURCES = \
src/path.c \
src/load-dropin.c \
src/execute.c \
src/exit-status.c \
src/dbus.c \
src/dbus-manager.c \
src/dbus-unit.c \
@ -604,7 +605,8 @@ systemctl_SOURCES = \
src/path-lookup.c \
src/sd-daemon.c \
src/cgroup-show.c \
src/cgroup-util.c
src/cgroup-util.c \
src/exit-status.c
systemctl_CFLAGS = \
$(AM_CFLAGS) \

6
fixme
View File

@ -58,11 +58,7 @@
* if a service fails too often, make the service enter maintenance mode, and the socket, too.
* exit code 5, 6 von sysv diensten ignorieren
* decode exit codes in systemctl status
* systemctl: ln -s output muss abschaltbar sein, und warning wenn [Install] leer ist.
* systemctl: warning wenn [Install] leer ist bei enable
* bash completion a la gdbus

View File

@ -51,6 +51,7 @@
#include "cgroup.h"
#include "namespace.h"
#include "tcpwrap.h"
#include "exit-status.h"
/* This assumes there is a 'tty' group */
#define TTY_MODE 0620
@ -1757,117 +1758,6 @@ int exec_command_set(ExecCommand *c, const char *path, ...) {
return 0;
}
const char* exit_status_to_string(ExitStatus status) {
/* We cast to int here, so that -Wenum doesn't complain that
* EXIT_SUCCESS/EXIT_FAILURE aren't in the enum */
switch ((int) status) {
case EXIT_SUCCESS:
return "SUCCESS";
case EXIT_FAILURE:
return "FAILURE";
case EXIT_INVALIDARGUMENT:
return "INVALIDARGUMENT";
case EXIT_NOTIMPLEMENTED:
return "NOTIMPLEMENTED";
case EXIT_NOPERMISSION:
return "NOPERMISSION";
case EXIT_NOTINSTALLED:
return "NOTINSSTALLED";
case EXIT_NOTCONFIGURED:
return "NOTCONFIGURED";
case EXIT_NOTRUNNING:
return "NOTRUNNING";
case EXIT_CHDIR:
return "CHDIR";
case EXIT_NICE:
return "NICE";
case EXIT_FDS:
return "FDS";
case EXIT_EXEC:
return "EXEC";
case EXIT_MEMORY:
return "MEMORY";
case EXIT_LIMITS:
return "LIMITS";
case EXIT_OOM_ADJUST:
return "OOM_ADJUST";
case EXIT_SIGNAL_MASK:
return "SIGNAL_MASK";
case EXIT_STDIN:
return "STDIN";
case EXIT_STDOUT:
return "STDOUT";
case EXIT_CHROOT:
return "CHROOT";
case EXIT_IOPRIO:
return "IOPRIO";
case EXIT_TIMERSLACK:
return "TIMERSLACK";
case EXIT_SECUREBITS:
return "SECUREBITS";
case EXIT_SETSCHEDULER:
return "SETSCHEDULER";
case EXIT_CPUAFFINITY:
return "CPUAFFINITY";
case EXIT_GROUP:
return "GROUP";
case EXIT_USER:
return "USER";
case EXIT_CAPABILITIES:
return "CAPABILITIES";
case EXIT_CGROUP:
return "CGROUP";
case EXIT_SETSID:
return "SETSID";
case EXIT_CONFIRM:
return "CONFIRM";
case EXIT_STDERR:
return "STDERR";
case EXIT_TCPWRAP:
return "TCPWRAP";
case EXIT_PAM:
return "PAM";
default:
return NULL;
}
}
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
[EXEC_INPUT_NULL] = "null",
[EXEC_INPUT_TTY] = "tty",

View File

@ -160,50 +160,6 @@ struct ExecContext {
bool timer_slack_nsec_set:1;
};
typedef enum ExitStatus {
/* EXIT_SUCCESS defined by libc */
/* EXIT_FAILURE defined by libc */
EXIT_INVALIDARGUMENT = 2,
EXIT_NOTIMPLEMENTED = 3,
EXIT_NOPERMISSION = 4,
EXIT_NOTINSTALLED = 5,
EXIT_NOTCONFIGURED = 6,
EXIT_NOTRUNNING = 7,
/* The LSB suggests that error codes >= 200 are "reserved". We
* use them here under the assumption that they hence are
* unused by init scripts.
*
* http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/iniscrptact.html */
EXIT_CHDIR = 200,
EXIT_NICE,
EXIT_FDS,
EXIT_EXEC,
EXIT_MEMORY,
EXIT_LIMITS,
EXIT_OOM_ADJUST,
EXIT_SIGNAL_MASK,
EXIT_STDIN,
EXIT_STDOUT,
EXIT_CHROOT, /* 210 */
EXIT_IOPRIO,
EXIT_TIMERSLACK,
EXIT_SECUREBITS,
EXIT_SETSCHEDULER,
EXIT_CPUAFFINITY,
EXIT_GROUP,
EXIT_USER,
EXIT_CAPABILITIES,
EXIT_CGROUP,
EXIT_SETSID, /* 220 */
EXIT_CONFIRM,
EXIT_STDERR,
EXIT_TCPWRAP,
EXIT_PAM
} ExitStatus;
int exec_spawn(ExecCommand *command,
char **argv,
const ExecContext *context,
@ -243,6 +199,4 @@ int exec_output_from_string(const char *s);
const char* exec_input_to_string(ExecInput i);
int exec_input_from_string(const char *s);
const char* exit_status_to_string(ExitStatus status);
#endif

View File

@ -57,6 +57,7 @@
#include "path-lookup.h"
#include "special.h"
#include "bus-errors.h"
#include "exit-status.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
@ -1885,7 +1886,9 @@ static int manager_dispatch_sigchld(Manager *m) {
(long unsigned) si.si_pid,
sigchld_code_to_string(si.si_code),
si.si_status,
strna(si.si_code == CLD_EXITED ? exit_status_to_string(si.si_status) : signal_to_string(si.si_status)));
strna(si.si_code == CLD_EXITED
? exit_status_to_string(si.si_status, EXIT_STATUS_FULL)
: signal_to_string(si.si_status)));
if (!u)
continue;

View File

@ -2263,7 +2263,10 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) {
assert(s);
assert(pid >= 0);
success = is_clean_exit(code, status);
if (s->sysv_path)
success = is_clean_exit_lsb(code, status);
else
success = is_clean_exit(code, status);
if (s->main_pid == pid) {

View File

@ -50,6 +50,7 @@
#include "conf-parser.h"
#include "sd-daemon.h"
#include "shutdownd.h"
#include "exit-status.h"
static const char *arg_type = NULL;
static char **arg_property = NULL;
@ -1489,7 +1490,8 @@ typedef struct UnitStatusInfo {
pid_t main_pid;
pid_t control_pid;
const char *status_text;
bool running;
bool running:1;
bool is_sysv:1;
usec_t start_timestamp;
usec_t exit_timestamp;
@ -1584,9 +1586,15 @@ static void print_status_info(UnitStatusInfo *i) {
printf("\t Exited: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
free(t);
if (p->code == CLD_EXITED)
if (p->code == CLD_EXITED) {
const char *c;
printf("status=%i", p->status);
else
if ((c = exit_status_to_string(p->status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
printf("/%s", c);
} else
printf("signal=%s", signal_to_string(p->status));
printf(")\n");
@ -1616,9 +1624,15 @@ static void print_status_info(UnitStatusInfo *i) {
} else if (i->exit_code > 0) {
printf(" (code=%s, ", sigchld_code_to_string(i->exit_code));
if (i->exit_code == CLD_EXITED)
if (i->exit_code == CLD_EXITED) {
const char *c;
printf("status=%i", i->exit_status);
else
if ((c = exit_status_to_string(i->exit_status, i->is_sysv ? EXIT_STATUS_LSB : EXIT_STATUS_SYSTEMD)))
printf("/%s", c);
} else
printf("signal=%s", signal_to_string(i->exit_status));
printf(")");
}
@ -1687,9 +1701,10 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
i->description = s;
else if (streq(name, "FragmentPath"))
i->path = s;
else if (streq(name, "SysVPath"))
else if (streq(name, "SysVPath")) {
i->is_sysv = true;
i->path = s;
else if (streq(name, "DefaultControlGroup"))
} else if (streq(name, "DefaultControlGroup"))
i->default_control_group = s;
else if (streq(name, "StatusText"))
i->status_text = s;

View File

@ -57,6 +57,7 @@
#include "log.h"
#include "strv.h"
#include "label.h"
#include "exit-status.h"
bool streq_ptr(const char *a, const char *b) {
@ -2398,6 +2399,16 @@ bool is_clean_exit(int code, int status) {
return false;
}
bool is_clean_exit_lsb(int code, int status) {
if (is_clean_exit(code, status))
return true;
return
code == CLD_EXITED &&
(status == EXIT_NOTINSTALLED || status == EXIT_NOTCONFIGURED);
}
bool is_device_path(const char *path) {
/* Returns true on paths that refer to a device, either in

View File

@ -253,6 +253,7 @@ char *format_timespan(char *buf, size_t l, usec_t t);
int make_stdio(int fd);
bool is_clean_exit(int code, int status);
bool is_clean_exit_lsb(int code, int status);
unsigned long long random_ull(void);