Report about syntax errors with metadata

The information about the unit for which files are being parsed
is passed all the way down. This way messages land in the journal
with proper UNIT=... or USER_UNIT=... attribution.

'systemctl status' and 'journalctl -u' not displaying those messages
has been a source of confusion for users, since the journal entry for
a misspelt setting was often logged quite a bit earlier than the
failure to start a unit.
Based-on-a-patch-by: default avatarOleksii Shevchuk <alxchk@gmail.com>
parent c1b6628d
......@@ -123,7 +123,7 @@ static void parse_conf(void) {
if (!f)
return;
r = config_parse(BOOTCHART_CONF, f,
r = config_parse(NULL, BOOTCHART_CONF, f,
NULL, config_item_table_lookup, (void*) items, true, NULL);
if (r < 0)
log_warning("Failed to parse configuration file: %s", strerror(-r));
......
......@@ -198,7 +198,9 @@ int unit_load_dropin(Unit *u) {
return 0;
STRV_FOREACH(f, u->dropin_paths) {
r = config_parse(*f, NULL, UNIT_VTABLE(u)->sections, config_item_perf_lookup, (void*) load_fragment_gperf_lookup, false, u);
r = config_parse(u->id, *f, NULL,
UNIT_VTABLE(u)->sections, config_item_perf_lookup,
(void*) load_fragment_gperf_lookup, false, u);
if (r < 0)
return r;
}
......
......@@ -34,6 +34,8 @@
#include <sys/time.h>
#include <sys/resource.h>
#include <systemd/sd-messages.h>
#include "unit.h"
#include "strv.h"
#include "conf-parser.h"
......@@ -51,30 +53,32 @@
#include "env-util.h"
#ifndef HAVE_SYSV_COMPAT
int config_parse_warn_compat(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
log_debug("[%s:%u] Support for option %s= has been disabled at compile time and is ignored", filename, line, lvalue);
int config_parse_warn_compat(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
"Support for option %s= has been disabled at compile time and is ignored",
lvalue);
return 0;
}
#endif
int config_parse_unit_deps(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_unit_deps(const char* unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
UnitDependency d = ltype;
Unit *u = userdata;
......@@ -100,22 +104,22 @@ int config_parse_unit_deps(
r = unit_add_dependency_by_name(u, d, k, NULL, true);
if (r < 0)
log_error("[%s:%u] Failed to add dependency on %s, ignoring: %s",
filename, line, k, strerror(-r));
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
}
return 0;
}
int config_parse_unit_string_printf(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_unit_string_printf(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
......@@ -127,21 +131,22 @@ int config_parse_unit_string_printf(
k = unit_full_printf(u, rvalue);
if (!k)
log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
return config_parse_string(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
return config_parse_string(unit, filename, line, section, lvalue, ltype,
k ? k : rvalue, data, userdata);
}
int config_parse_unit_strv_printf(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_unit_strv_printf(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
......@@ -153,21 +158,22 @@ int config_parse_unit_strv_printf(
k = unit_full_printf(u, rvalue);
if (!k)
log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
return config_parse_strv(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
return config_parse_strv(unit, filename, line, section, lvalue, ltype,
k ? k : rvalue, data, userdata);
}
int config_parse_unit_path_printf(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_unit_path_printf(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Unit *u = userdata;
_cleanup_free_ char *k = NULL;
......@@ -179,21 +185,22 @@ int config_parse_unit_path_printf(
k = unit_full_printf(u, rvalue);
if (!k)
log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
return config_parse_path(filename, line, section, lvalue, ltype, k ? k : rvalue, data, userdata);
return config_parse_path(unit, filename, line, section, lvalue, ltype,
k ? k : rvalue, data, userdata);
}
int config_parse_socket_listen(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_socket_listen(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
SocketPort *p, *tail;
Socket *s;
......@@ -225,8 +232,8 @@ int config_parse_socket_listen(
free(p);
return log_oom();
} else
log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
}
path_kill_slashes(p->path);
......@@ -238,12 +245,13 @@ int config_parse_socket_listen(
p->type = SOCKET_SOCKET;
k = unit_full_printf(UNIT(s), rvalue);
if (!k)
log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
if (r < 0) {
log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to parse address value, ignoring: %s", rvalue);
free(p);
return 0;
}
......@@ -255,12 +263,13 @@ int config_parse_socket_listen(
p->type = SOCKET_SOCKET;
k = unit_full_printf(UNIT(s), rvalue);
if (!k)
log_error("[%s:%u] Failed to resolve unit specifiers on %s. Ignoring.",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
r = socket_address_parse(&p->address, k ? k : rvalue);
if (r < 0) {
log_error("[%s:%u] Failed to parse address value, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to parse address value, ignoring: %s", rvalue);
free(p);
return 0;
}
......@@ -275,7 +284,8 @@ int config_parse_socket_listen(
}
if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
log_error("[%s:%u] Address family not supported, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
"Address family not supported, ignoring: %s", rvalue);
free(p);
return 0;
}
......@@ -292,15 +302,15 @@ int config_parse_socket_listen(
return 0;
}
int config_parse_socket_bind(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_socket_bind(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Socket *s;
SocketAddressBindIPv6Only b;
......@@ -318,7 +328,8 @@ int config_parse_socket_bind(
r = parse_boolean(rvalue);
if (r < 0) {
log_error("[%s:%u] Failed to parse bind IPv6 only value, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
return 0;
}
......@@ -329,31 +340,34 @@ int config_parse_socket_bind(
return 0;
}
int config_parse_exec_nice(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_nice(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
int priority;
int priority, r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (safe_atoi(rvalue, &priority) < 0) {
log_error("[%s:%u] Failed to parse nice priority, ignoring: %s. ", filename, line, rvalue);
r = safe_atoi(rvalue, &priority);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to parse nice priority, ignoring: %s. ", rvalue);
return 0;
}
if (priority < PRIO_MIN || priority >= PRIO_MAX) {
log_error("[%s:%u] Nice priority out of range, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, ERANGE,
"Nice priority out of range, ignoring: %s", rvalue);
return 0;
}
......@@ -363,31 +377,34 @@ int config_parse_exec_nice(
return 0;
}
int config_parse_exec_oom_score_adjust(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_oom_score_adjust(const char* unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
int oa;
int oa, r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (safe_atoi(rvalue, &oa) < 0) {
log_error("[%s:%u] Failed to parse the OOM score adjust value, ignoring: %s", filename, line, rvalue);
r = safe_atoi(rvalue, &oa);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
return 0;
}
if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
log_error("[%s:%u] OOM score adjust value out of range, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, ERANGE,
"OOM score adjust value out of range, ignoring: %s", rvalue);
return 0;
}
......@@ -397,15 +414,15 @@ int config_parse_exec_oom_score_adjust(
return 0;
}
int config_parse_exec(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecCommand **e = data, *nce;
char *path, **n;
......@@ -458,8 +475,8 @@ int config_parse_exec(
}
if (*rvalue != '/') {
log_error("[%s:%u] Executable path is not absolute, ignoring: %s",
filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Executable path is not absolute, ignoring: %s", rvalue);
return 0;
}
......@@ -492,7 +509,9 @@ int config_parse_exec(
}
if (!utf8_is_valid(path)) {
log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Path is not UTF-8 clean, ignoring assignment: %s",
rvalue);
r = 0;
goto fail;
}
......@@ -507,7 +526,9 @@ int config_parse_exec(
}
if (!utf8_is_valid(c)) {
log_error("[%s:%u] Path is not UTF-8 clean, ignoring assignment: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Path is not UTF-8 clean, ignoring assignment: %s",
rvalue);
r = 0;
goto fail;
}
......@@ -517,7 +538,8 @@ int config_parse_exec(
n[k] = NULL;
if (!n[0]) {
log_error("[%s:%u] Invalid command line, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Invalid command line, ignoring: %s", rvalue);
r = 0;
goto fail;
}
......@@ -563,15 +585,15 @@ fail:
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
int config_parse_socket_bindtodevice(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_socket_bindtodevice(const char* unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
Socket *s = data;
char *n;
......@@ -597,15 +619,15 @@ int config_parse_socket_bindtodevice(
DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
int config_parse_exec_io_class(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_io_class(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
int x;
......@@ -617,7 +639,8 @@ int config_parse_exec_io_class(
x = ioprio_class_from_string(rvalue);
if (x < 0) {
log_error("[%s:%u] Failed to parse IO scheduling class, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, EINVAL,
"Failed to parse IO scheduling class, ignoring: %s", rvalue);
return 0;
}
......@@ -627,26 +650,28 @@ int config_parse_exec_io_class(
return 0;
}
int config_parse_exec_io_priority(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_io_priority(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
int i;
int i, r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
log_error("[%s:%u] Failed to parse io priority, ignoring: %s", filename, line, rvalue);
r = safe_atoi(rvalue, &i);
if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to parse IO priority, ignoring: %s", rvalue);
return 0;
}
......@@ -656,15 +681,15 @@ int config_parse_exec_io_priority(
return 0;
}
int config_parse_exec_cpu_sched_policy(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_cpu_sched_policy(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
......@@ -677,7 +702,8 @@ int config_parse_exec_cpu_sched_policy(
x = sched_policy_from_string(rvalue);
if (x < 0) {
log_error("[%s:%u] Failed to parse CPU scheduling policy, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, -x,
"Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
return 0;
}
......@@ -689,26 +715,28 @@ int config_parse_exec_cpu_sched_policy(
return 0;
}
int config_parse_exec_cpu_sched_prio(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_cpu_sched_prio(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;
int i, min, max;
int i, min, max, r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
if (safe_atoi(rvalue, &i) < 0) {
log_error("[%s:%u] Failed to parse CPU scheduling priority, ignoring: %s", filename, line, rvalue);
r = safe_atoi(rvalue, &i);
if (r < 0) {
log_syntax(unit, LOG_ERR, filename, line, -r,
"Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
return 0;
}
......@@ -717,7 +745,8 @@ int config_parse_exec_cpu_sched_prio(
max = sched_get_priority_max(c->cpu_sched_policy);
if (i < min || i > max) {
log_error("[%s:%u] CPU scheduling priority is out of range, ignoring: %s", filename, line, rvalue);
log_syntax(unit, LOG_ERR, filename, line, ERANGE,
"CPU scheduling priority is out of range, ignoring: %s", rvalue);
return 0;
}
......@@ -727,15 +756,15 @@ int config_parse_exec_cpu_sched_prio(
return 0;
}
int config_parse_exec_cpu_affinity(
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
int config_parse_exec_cpu_affinity(const char *unit,
const char *filename,
unsigned line,
const char *section,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
ExecContext *c = data;