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.
This commit is contained in:
Beniamino Galvani 2023-02-14 09:23:51 +01:00
parent 7037aa66c6
commit d65702803c

View file

@ -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;