summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-11-27 19:48:02 +0100
committerLennart Poettering <lennart@poettering.net>2014-11-27 22:05:23 +0100
commit086891e5c119abb9854237fc32e736fe2d67234c (patch)
tree4fc81d73413d1f1aa351e0de248307180c8893de /src/shared
parentfb6d9b77a71a5f007392b754bf7d8e06a6bed69a (diff)
log: add an "error" parameter to all low-level logging calls and intrdouce log_error_errno() as log calls that take error numbers
This change has two benefits: - The format string %m will now resolve to the specified error (or to errno if the specified error is 0. This allows getting rid of a ton of strerror() invocations, a function that is not thread-safe. - The specified error can be passed to the journal in the ERRNO= field. Now of course, we just need somebody to convert all cases of this: log_error("Something happened: %s", strerror(-r)); into thus: log_error_errno(-r, "Something happened: %m");
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/conf-parser.c18
-rw-r--r--src/shared/conf-parser.h14
-rw-r--r--src/shared/log.c218
-rw-r--r--src/shared/log.h49
4 files changed, 179 insertions, 120 deletions
diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c
index 027c49ce3b..6bd9d9ebf7 100644
--- a/src/shared/conf-parser.c
+++ b/src/shared/conf-parser.c
@@ -38,10 +38,16 @@
#include "exit-status.h"
#include "sd-messages.h"
-int log_syntax_internal(const char *unit, int level,
- const char *file, unsigned line, const char *func,
- const char *config_file, unsigned config_line,
- int error, const char *format, ...) {
+int log_syntax_internal(
+ const char *unit,
+ int level,
+ const char *file,
+ int line,
+ const char *func,
+ const char *config_file,
+ unsigned config_line,
+ int error,
+ const char *format, ...) {
_cleanup_free_ char *msg = NULL;
int r;
@@ -55,21 +61,21 @@ int log_syntax_internal(const char *unit, int level,
if (unit)
r = log_struct_internal(level,
+ error > 0 ? error : EINVAL,
file, line, func,
getpid() == 1 ? "UNIT=%s" : "USER_UNIT=%s", unit,
MESSAGE_ID(SD_MESSAGE_CONFIG_ERROR),
"CONFIG_FILE=%s", config_file,
"CONFIG_LINE=%u", config_line,
- "ERRNO=%d", error > 0 ? error : EINVAL,
"MESSAGE=[%s:%u] %s", config_file, config_line, msg,
NULL);
else
r = log_struct_internal(level,
+ error > 0 ? error : EINVAL,
file, line, func,
MESSAGE_ID(SD_MESSAGE_CONFIG_ERROR),
"CONFIG_FILE=%s", config_file,
"CONFIG_LINE=%u", config_line,
- "ERRNO=%d", error > 0 ? error : EINVAL,
"MESSAGE=[%s:%u] %s", config_file, config_line, msg,
NULL);
diff --git a/src/shared/conf-parser.h b/src/shared/conf-parser.h
index 69d32711b7..2507a44444 100644
--- a/src/shared/conf-parser.h
+++ b/src/shared/conf-parser.h
@@ -119,10 +119,16 @@ int config_parse_mode(const char *unit, const char *filename, unsigned line, con
int config_parse_log_facility(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_log_level(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int log_syntax_internal(const char *unit, int level,
- const char *file, unsigned line, const char *func,
- const char *config_file, unsigned config_line,
- int error, const char *format, ...) _printf_(9, 10);
+int log_syntax_internal(
+ const char *unit,
+ int level,
+ const char *file,
+ int line,
+ const char *func,
+ const char *config_file,
+ unsigned config_line,
+ int error,
+ const char *format, ...) _printf_(9, 10);
#define log_syntax(unit, level, config_file, config_line, error, ...) \
log_syntax_internal(unit, level, \
diff --git a/src/shared/log.c b/src/shared/log.c
index d465311d02..ba959b914e 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -122,7 +122,7 @@ static int create_log_socket(int type) {
timeval_store(&tv, 10 * USEC_PER_MSEC);
else
timeval_store(&tv, 10 * USEC_PER_SEC);
- (void)setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
+ (void) setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
return fd;
}
@@ -302,10 +302,11 @@ void log_set_facility(int facility) {
static int write_to_console(
int level,
+ int error,
const char*file,
int line,
const char *func,
- const char *object_name,
+ const char *object_field,
const char *object,
const char *buffer) {
@@ -356,13 +357,14 @@ static int write_to_console(
}
static int write_to_syslog(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *object_name,
- const char *object,
- const char *buffer) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *object_field,
+ const char *object,
+ const char *buffer) {
char header_priority[16], header_time[64], header_pid[16];
struct iovec iovec[5] = {};
@@ -418,13 +420,14 @@ static int write_to_syslog(
}
static int write_to_kmsg(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *object_name,
- const char *object,
- const char *buffer) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *object_field,
+ const char *object,
+ const char *buffer) {
char header_priority[16], header_pid[16];
struct iovec iovec[5] = {};
@@ -450,45 +453,55 @@ static int write_to_kmsg(
return 1;
}
-static int log_do_header(char *header, size_t size,
- int level,
- const char *file, int line, const char *func,
- const char *object_name, const char *object) {
+static int log_do_header(
+ char *header,
+ size_t size,
+ int level,
+ int error,
+ const char *file, int line, const char *func,
+ const char *object_field, const char *object) {
+
snprintf(header, size,
"PRIORITY=%i\n"
"SYSLOG_FACILITY=%i\n"
- "%s%.*s%s"
+ "%s%s%s"
"%s%.*i%s"
- "%s%.*s%s"
- "%s%.*s%s"
+ "%s%s%s"
+ "%s%.*i%s"
+ "%s%s%s"
"SYSLOG_IDENTIFIER=%s\n",
LOG_PRI(level),
LOG_FAC(level),
- file ? "CODE_FILE=" : "",
- file ? LINE_MAX : 0, file, /* %.0s means no output */
- file ? "\n" : "",
+ isempty(file) ? "" : "CODE_FILE=",
+ isempty(file) ? "" : file,
+ isempty(file) ? "" : "\n",
line ? "CODE_LINE=" : "",
line ? 1 : 0, line, /* %.0d means no output too, special case for 0 */
line ? "\n" : "",
- func ? "CODE_FUNCTION=" : "",
- func ? LINE_MAX : 0, func,
- func ? "\n" : "",
- object ? object_name : "",
- object ? LINE_MAX : 0, object, /* %.0s means no output */
- object ? "\n" : "",
+ isempty(func) ? "" : "CODE_FUNCTION=",
+ isempty(func) ? "" : func,
+ isempty(func) ? "" : "\n",
+ error ? "ERRNO=" : "",
+ error ? 1 : 0, error,
+ error ? "\n" : "",
+ isempty(object) ? "" : object_field,
+ isempty(object) ? "" : object,
+ isempty(object) ? "" : "\n",
program_invocation_short_name);
header[size - 1] = '\0';
+
return 0;
}
static int write_to_journal(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *object_name,
- const char *object,
- const char *buffer) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *object_field,
+ const char *object,
+ const char *buffer) {
char header[LINE_MAX];
struct iovec iovec[4] = {};
@@ -497,8 +510,7 @@ static int write_to_journal(
if (journal_fd < 0)
return 0;
- log_do_header(header, sizeof(header), level,
- file, line, func, object_name, object);
+ log_do_header(header, sizeof(header), level, error, file, line, func, object_field, object);
IOVEC_SET_STRING(iovec[0], header);
IOVEC_SET_STRING(iovec[1], "MESSAGE=");
@@ -515,13 +527,14 @@ static int write_to_journal(
}
static int log_dispatch(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *object_name,
- const char *object,
- char *buffer) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *object_field,
+ const char *object,
+ char *buffer) {
int r = 0;
@@ -548,8 +561,7 @@ static int log_dispatch(
log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
log_target == LOG_TARGET_JOURNAL) {
- k = write_to_journal(level, file, line, func,
- object_name, object, buffer);
+ k = write_to_journal(level, error, file, line, func, object_field, object, buffer);
if (k < 0) {
if (k != -EAGAIN)
log_close_journal();
@@ -561,8 +573,7 @@ static int log_dispatch(
if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
log_target == LOG_TARGET_SYSLOG) {
- k = write_to_syslog(level, file, line, func,
- object_name, object, buffer);
+ k = write_to_syslog(level, error, file, line, func, object_field, object, buffer);
if (k < 0) {
if (k != -EAGAIN)
log_close_syslog();
@@ -578,8 +589,7 @@ static int log_dispatch(
log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
log_target == LOG_TARGET_KMSG)) {
- k = write_to_kmsg(level, file, line, func,
- object_name, object, buffer);
+ k = write_to_kmsg(level, error, file, line, func, object_field, object, buffer);
if (k < 0) {
log_close_kmsg();
log_open_console();
@@ -588,8 +598,7 @@ static int log_dispatch(
}
if (k <= 0) {
- k = write_to_console(level, file, line, func,
- object_name, object, buffer);
+ k = write_to_console(level, error, file, line, func, object_field, object, buffer);
if (k < 0)
return k;
}
@@ -602,6 +611,7 @@ static int log_dispatch(
int log_dump_internal(
int level,
+ int error,
const char*file,
int line,
const char *func,
@@ -614,16 +624,17 @@ int log_dump_internal(
if (_likely_(LOG_PRI(level) > log_max_level))
return 0;
- return log_dispatch(level, file, line, func, NULL, NULL, buffer);
+ return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
}
int log_metav(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format,
- va_list ap) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *format,
+ va_list ap) {
PROTECT_ERRNO;
char buffer[LINE_MAX];
@@ -631,38 +642,44 @@ int log_metav(
if (_likely_(LOG_PRI(level) > log_max_level))
return 0;
+ /* Make sure that %m maps to the specified error */
+ if (error != 0)
+ errno = error;
+
vsnprintf(buffer, sizeof(buffer), format, ap);
char_array_0(buffer);
- return log_dispatch(level, file, line, func, NULL, NULL, buffer);
+ return log_dispatch(level, error, file, line, func, NULL, NULL, buffer);
}
int log_meta(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *format, ...) {
int r;
va_list ap;
va_start(ap, format);
- r = log_metav(level, file, line, func, format, ap);
+ r = log_metav(level, error, file, line, func, format, ap);
va_end(ap);
return r;
}
int log_metav_object(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *object_name,
- const char *object,
- const char *format,
- va_list ap) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *object_field,
+ const char *object,
+ const char *format,
+ va_list ap) {
PROTECT_ERRNO;
char buffer[LINE_MAX];
@@ -670,34 +687,44 @@ int log_metav_object(
if (_likely_(LOG_PRI(level) > log_max_level))
return 0;
+ /* Make sure that %m maps to the specified error */
+ if (error != 0)
+ errno = error;
+
vsnprintf(buffer, sizeof(buffer), format, ap);
char_array_0(buffer);
- return log_dispatch(level, file, line, func,
- object_name, object, buffer);
+ return log_dispatch(level, error, file, line, func, object_field, object, buffer);
}
int log_meta_object(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *object_name,
- const char *object,
- const char *format, ...) {
+ int level,
+ int error,
+ const char*file,
+ int line,
+ const char *func,
+ const char *object_field,
+ const char *object,
+ const char *format, ...) {
int r;
va_list ap;
va_start(ap, format);
- r = log_metav_object(level, file, line, func,
- object_name, object, format, ap);
+ r = log_metav_object(level, error, file, line, func, object_field, object, format, ap);
va_end(ap);
return r;
}
-static void log_assert(int level, const char *text, const char *file, int line, const char *func, const char *format) {
+static void log_assert(
+ int level,
+ const char *text,
+ const char *file,
+ int line,
+ const char *func,
+ const char *format) {
+
static char buffer[LINE_MAX];
if (_likely_(LOG_PRI(level) > log_max_level))
@@ -710,7 +737,7 @@ static void log_assert(int level, const char *text, const char *file, int line,
char_array_0(buffer);
log_abort_msg = buffer;
- log_dispatch(level, file, line, func, NULL, NULL, buffer);
+ log_dispatch(level, 0, file, line, func, NULL, NULL, buffer);
}
noreturn void log_assert_failed(const char *text, const char *file, int line, const char *func) {
@@ -729,12 +756,13 @@ void log_assert_failed_return(const char *text, const char *file, int line, cons
}
int log_oom_internal(const char *file, int line, const char *func) {
- log_meta(LOG_ERR, file, line, func, "Out of memory.");
+ log_meta(LOG_ERR, ENOMEM, file, line, func, "Out of memory.");
return -ENOMEM;
}
int log_struct_internal(
int level,
+ int error,
const char *file,
int line,
const char *func,
@@ -767,8 +795,7 @@ int log_struct_internal(
static const char nl = '\n';
/* If the journal is available do structured logging */
- log_do_header(header, sizeof(header), level,
- file, line, func, NULL, NULL);
+ log_do_header(header, sizeof(header), level, error, file, line, func, NULL, NULL);
IOVEC_SET_STRING(iovec[n++], header);
va_start(ap, format);
@@ -840,8 +867,7 @@ int log_struct_internal(
va_end(ap);
if (found)
- r = log_dispatch(level, file, line, func,
- NULL, NULL, buf + 8);
+ r = log_dispatch(level, error, file, line, func, NULL, NULL, buf + 8);
else
r = -EINVAL;
}
diff --git a/src/shared/log.h b/src/shared/log.h
index 8141e9dbb0..9dd68df500 100644
--- a/src/shared/log.h
+++ b/src/shared/log.h
@@ -77,44 +77,49 @@ void log_parse_environment(void);
int log_meta(
int level,
+ int error,
const char*file,
int line,
const char *func,
- const char *format, ...) _printf_(5,6);
+ const char *format, ...) _printf_(6,7);
int log_metav(
int level,
+ int error,
const char*file,
int line,
const char *func,
const char *format,
- va_list ap) _printf_(5,0);
+ va_list ap) _printf_(6,0);
int log_meta_object(
int level,
+ int error,
const char*file,
int line,
const char *func,
const char *object_name,
const char *object,
- const char *format, ...) _printf_(7,8);
+ const char *format, ...) _printf_(8,9);
int log_metav_object(
int level,
+ int error,
const char*file,
int line,
const char *func,
const char *object_name,
const char *object,
const char *format,
- va_list ap) _printf_(7,0);
+ va_list ap) _printf_(8,0);
int log_struct_internal(
int level,
+ int error,
const char *file,
int line,
const char *func,
- const char *format, ...) _printf_(5,0) _sentinel_;
+ const char *format, ...) _printf_(6,0) _sentinel_;
int log_oom_internal(
const char *file,
@@ -124,11 +129,13 @@ int log_oom_internal(
/* This modifies the buffer passed! */
int log_dump_internal(
int level,
+ int error,
const char*file,
int line,
const char *func,
char *buffer);
+/* Logging for various assertions */
noreturn void log_assert_failed(
const char *text,
const char *file,
@@ -147,12 +154,16 @@ void log_assert_failed_return(
int line,
const char *func);
-#define log_full(level, ...) \
-do { \
- if (log_get_max_level() >= (level)) \
- log_meta((level), __FILE__, __LINE__, __func__, __VA_ARGS__); \
-} while (0)
+/* Logging with level */
+#define log_full_errno(level, error, ...) \
+ do { \
+ if (log_get_max_level() >= (level)) \
+ log_meta((level), error, __FILE__, __LINE__, __func__, __VA_ARGS__); \
+ } while (false)
+#define log_full(level, ...) log_full_errno(level, 0, __VA_ARGS__)
+
+/* Normal logging */
#define log_debug(...) log_full(LOG_DEBUG, __VA_ARGS__)
#define log_info(...) log_full(LOG_INFO, __VA_ARGS__)
#define log_notice(...) log_full(LOG_NOTICE, __VA_ARGS__)
@@ -160,18 +171,28 @@ do { \
#define log_error(...) log_full(LOG_ERR, __VA_ARGS__)
#define log_emergency(...) log_full(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__)
+/* Logging triggered by an errno-like error */
+#define log_debug_errno(error, ...) log_full_errno(LOG_DEBUG, error, __VA_ARGS__)
+#define log_info_errno(error, ...) log_full_errno(LOG_INFO, error, __VA_ARGS__)
+#define log_notice_errno(error, ...) log_full_errno(LOG_NOTICE, error, __VA_ARGS__)
+#define log_warning_errno(error, ...) log_full_errno(LOG_WARNING, error, __VA_ARGS__)
+#define log_error_errno(error, ...) log_full_errno(LOG_ERR, error, __VA_ARGS__)
+#define log_emergency_errno(error, ...) log_full_errno(getpid() == 1 ? LOG_EMERG : LOG_ERR, __VA_ARGS__)
+
#ifdef LOG_TRACE
# define log_trace(...) log_debug(__VA_ARGS__)
#else
# define log_trace(...) do {} while(0)
#endif
-#define log_struct(level, ...) log_struct_internal(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
-
-#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
+/* Structured logging */
+#define log_struct(level, ...) log_struct_internal(level, 0, __FILE__, __LINE__, __func__, __VA_ARGS__)
+#define log_struct_errno(level, error, ...) log_struct_internal(level, error, __FILE__, __LINE__, __func__, __VA_ARGS__)
/* This modifies the buffer passed! */
-#define log_dump(level, buffer) log_dump_internal(level, __FILE__, __LINE__, __func__, buffer)
+#define log_dump(level, buffer) log_dump_internal(level, 0, __FILE__, __LINE__, __func__, buffer)
+
+#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
bool log_on_console(void) _pure_;