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:55:30 +0100
commitf1f1aee711515244322a37150de908e26cfa240f (patch)
tree932755a6b2f35ca23acf9e8de6b86bbfa035d4cb
parent7e3dccb781346863ec373f1ea4baf14aa9052878 (diff)
downloadNetworkManager-f1f1aee711515244322a37150de908e26cfa240f.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. (cherry picked from commit d65702803cb02ddd656f13917a8a9af7bc08b90a)
-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 da129eb696..500bffb98d 100644
--- a/src/core/nm-core-utils.c
+++ b/src/core/nm-core-utils.c
@@ -4868,11 +4868,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;
@@ -4908,13 +4911,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);
@@ -4928,6 +4935,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);
@@ -5023,6 +5034,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)
{
@@ -5098,10 +5127,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,
@@ -5130,6 +5160,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);
@@ -5155,6 +5187,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;