summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBeniamino Galvani <bgalvani@redhat.com>2023-02-14 09:23:51 +0100
committerBeniamino Galvani <bgalvani@redhat.com>2023-02-21 13:46:54 +0100
commitd65702803cb02ddd656f13917a8a9af7bc08b90a (patch)
tree0e3e955f462ba16de51f3c0d35517c545dc7234f
parent7037aa66c6fce01d3e33e1fae32c35fb1f25b363 (diff)
downloadNetworkManager-d65702803cb02ddd656f13917a8a9af7bc08b90a.tar.gz
core: print stderr from nm-daemon-helper
Currently the only way to return an error code from the daemon helper is via the process exit code, but that is not enough to fully describe an error from getaddrinfo(); in fact, the function returns a EAI_* error code and when the value is EAI_SYSTEM, the error code is returned in errno. At the moment, any messages printed to stderr by the helper goes to NM stderr; instead, we want to capture it and pass it through the logging mechanism of NM, so that it can be filtered according to level and domain.
-rw-r--r--src/core/nm-core-utils.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/core/nm-core-utils.c b/src/core/nm-core-utils.c
index 2c251855bf..15b3c6a80a 100644
--- a/src/core/nm-core-utils.c
+++ b/src/core/nm-core-utils.c
@@ -4866,11 +4866,14 @@ typedef struct {
int child_stdin;
int child_stdout;
+ int child_stderr;
GSource *input_source;
GSource *output_source;
+ GSource *error_source;
NMStrBuf in_buffer;
NMStrBuf out_buffer;
+ NMStrBuf err_buffer;
gsize out_buffer_offset;
} HelperInfo;
@@ -4906,13 +4909,17 @@ helper_info_free(gpointer data)
nm_str_buf_destroy(&info->in_buffer);
nm_str_buf_destroy(&info->out_buffer);
+ nm_str_buf_destroy(&info->err_buffer);
nm_clear_g_source_inst(&info->input_source);
nm_clear_g_source_inst(&info->output_source);
+ nm_clear_g_source_inst(&info->error_source);
if (info->child_stdout != -1)
nm_close(info->child_stdout);
if (info->child_stdin != -1)
nm_close(info->child_stdin);
+ if (info->child_stderr != -1)
+ nm_close(info->child_stderr);
if (info->pid != -1) {
nm_assert(info->pid > 1);
@@ -4926,6 +4933,10 @@ static void
helper_complete(HelperInfo *info, GError *error)
{
if (error) {
+ if (info->err_buffer.len > 0) {
+ _LOG2T(info, "stderr: %s", nm_str_buf_get_str(&info->err_buffer));
+ }
+
nm_clear_g_cancellable_disconnect(g_task_get_cancellable(info->task),
&info->cancellable_id);
g_task_return_error(info->task, error);
@@ -5021,6 +5032,24 @@ helper_have_data(int fd, GIOCondition condition, gpointer user_data)
return G_SOURCE_CONTINUE;
}
+static gboolean
+helper_have_err_data(int fd, GIOCondition condition, gpointer user_data)
+{
+ HelperInfo *info = user_data;
+ gssize n_read;
+
+ n_read = nm_utils_fd_read(fd, &info->err_buffer);
+
+ if (n_read > 0)
+ return G_SOURCE_CONTINUE;
+
+ nm_clear_g_source_inst(&info->error_source);
+ nm_close(info->child_stderr);
+ info->child_stderr = -1;
+
+ return G_SOURCE_CONTINUE;
+}
+
static void
helper_child_terminated(GPid pid, int status, gpointer user_data)
{
@@ -5096,10 +5125,11 @@ nm_utils_spawn_helper(const char *const *args,
&info->pid,
&info->child_stdin,
&info->child_stdout,
- NULL,
+ &info->child_stderr,
&error)) {
info->child_stdin = -1;
info->child_stdout = -1;
+ info->child_stderr = -1;
info->pid = -1;
g_task_return_error(info->task,
g_error_new(NM_UTILS_ERROR,
@@ -5128,6 +5158,8 @@ nm_utils_spawn_helper(const char *const *args,
fcntl(info->child_stdin, F_SETFL, fd_flags | O_NONBLOCK);
fd_flags = fcntl(info->child_stdout, F_GETFD, 0);
fcntl(info->child_stdout, F_SETFL, fd_flags | O_NONBLOCK);
+ fd_flags = fcntl(info->child_stderr, F_GETFD, 0);
+ fcntl(info->child_stderr, F_SETFL, fd_flags | O_NONBLOCK);
/* Watch process stdin */
info->out_buffer = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, TRUE);
@@ -5153,6 +5185,16 @@ nm_utils_spawn_helper(const char *const *args,
NULL);
g_source_attach(info->input_source, g_main_context_get_thread_default());
+ /* Watch process stderr */
+ info->err_buffer = NM_STR_BUF_INIT(0, FALSE);
+ info->error_source = nm_g_unix_fd_source_new(info->child_stderr,
+ G_IO_IN | G_IO_ERR | G_IO_HUP,
+ G_PRIORITY_DEFAULT,
+ helper_have_err_data,
+ info,
+ NULL);
+ g_source_attach(info->error_source, g_main_context_get_thread_default());
+
if (cancellable) {
gulong signal_id;