qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 2/3] qga: Add optional `merge-output` flag to guest-exec qapi


From: Marc-André Lureau
Subject: Re: [PATCH 2/3] qga: Add optional `merge-output` flag to guest-exec qapi
Date: Tue, 28 Feb 2023 12:18:11 +0400

Hi

On Tue, Feb 28, 2023 at 5:15 AM Daniel Xu <dxu@dxuuu.xyz> wrote:
>
> Hi,
>
> On Mon, Feb 27, 2023, at 1:22 AM, Marc-André Lureau wrote:
> > Hi
> >
> > On Fri, Feb 24, 2023 at 8:31 AM Daniel Xu <dxu@dxuuu.xyz> wrote:
> >>
> >> Currently, the captured output (via `capture-output`) is segregated into
> >> separate GuestExecStatus fields (`out-data` and `err-data`). This means
> >> that downstream consumers have no way to reassemble the captured data
> >> back into the original stream.
> >>
> >> This is relevant for chatty and semi-interactive (ie. read only) CLI
> >> tools.  Such tools may deliberately interleave stdout and stderr for
> >> visual effect. If segregated, the output becomes harder to visually
> >> understand.
> >>
> >> This commit adds a new optional flag to the guest-exec qapi to merge the
> >> output streams such that consumers can have a pristine view of the
> >> original command output.
> >>
> >> Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
> >> ---
> >>  qga/commands.c       | 13 ++++++++++++-
> >>  qga/qapi-schema.json |  6 +++++-
> >>  2 files changed, 17 insertions(+), 2 deletions(-)
> >>
> >> diff --git a/qga/commands.c b/qga/commands.c
> >> index 360077364e..14b970e768 100644
> >> --- a/qga/commands.c
> >> +++ b/qga/commands.c
> >> @@ -274,6 +274,15 @@ static void guest_exec_child_watch(GPid pid, gint 
> >> status, gpointer data)
> >>  /** Reset ignored signals back to default. */
> >>  static void guest_exec_task_setup(gpointer data)
> >>  {
> >> +    bool has_merge = *(bool *)data;
> >> +
> >> +    if (has_merge) {
> >> +        if (dup2(STDOUT_FILENO, STDERR_FILENO) != 0) {
> >> +            slog("dup2() failed to merge stderr into stdout: %s",
> >> +                 strerror(errno));
> >> +        }
> >> +    }
> >
> > https://docs.gtk.org/glib/callback.SpawnChildSetupFunc.html
> >
> > "On Windows, the function is called in the parent. Its usefulness on
> > Windows is thus questionable. In many cases executing the child setup
> > function in the parent can have ill effects, and you should be very
> > careful when porting software to Windows that uses child setup
> > functions."
> >
> > It looks like this would be bad.
>
> Ah that's a good catch. I'm not very familiar with windows APIs so
> unfortunately I don't have any good ideas here.
>
> Best I can tell g_spawn_async_with_pipes_and_fds() work with it's
> source_fds and target_fds mapping. But it looks like that came in
> glib 2.68 so we cannot use it yet.

g_spawn_async_with_fds() is from 2.58.. but we still depend on 2.56,
because of CentOS 8. And it seems we will have to wait until Dec 2023
to bump it.

I don't know whether it would be acceptable to simply return an error
when using 'merge-output' on old host (with glib < 2.58).

 Otherwise, I think you should use g_spawn_async_with_fds() when
possible, and use the ChildSetupFunc fallback, but only on Unix (for
CentOS 8!).

>
> How about limiting this merge-output flag to linux/unix systems
> for now? Could document this in the qapi doc string.
>
> >
> >> +
> >>  #if !defined(G_OS_WIN32)
> >>      struct sigaction sigact;
> >>
> >> @@ -385,6 +394,7 @@ GuestExec *qmp_guest_exec(const char *path,
> >>                         bool has_env, strList *env,
> >>                         const char *input_data,
> >>                         bool has_capture_output, bool capture_output,
> >> +                       bool has_merge_output, bool merge_output,
> >>                         Error **errp)
> >>  {
> >>      GPid pid;
> >> @@ -398,6 +408,7 @@ GuestExec *qmp_guest_exec(const char *path,
> >>      GIOChannel *in_ch, *out_ch, *err_ch;
> >>      GSpawnFlags flags;
> >>      bool has_output = (has_capture_output && capture_output);
> >> +    bool has_merge = (has_merge_output && merge_output);
> >>      g_autofree uint8_t *input = NULL;
> >>      size_t ninput = 0;
> >>
> >> @@ -421,7 +432,7 @@ GuestExec *qmp_guest_exec(const char *path,
> >>      }
> >>
> >>      ret = g_spawn_async_with_pipes(NULL, argv, envp, flags,
> >> -            guest_exec_task_setup, NULL, &pid, input_data ? &in_fd : NULL,
> >> +            guest_exec_task_setup, &has_merge, &pid, input_data ? &in_fd 
> >> : NULL,
> >>              has_output ? &out_fd : NULL, has_output ? &err_fd : NULL, 
> >> &gerr);
> >>      if (!ret) {
> >>          error_setg(errp, QERR_QGA_COMMAND_FAILED, gerr->message);
> >> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> >> index 796434ed34..4192fcc5a4 100644
> >> --- a/qga/qapi-schema.json
> >> +++ b/qga/qapi-schema.json
> >> @@ -1211,6 +1211,9 @@
> >>  # @input-data: data to be passed to process stdin (base64 encoded)
> >>  # @capture-output: bool flag to enable capture of
> >>  #                  stdout/stderr of running process. defaults to false.
> >> +# @merge-output: bool flag to merge stdout/stderr of running process
> >> +#                into stdout. only effective if used with @capture-output.
> >> +#                defaults to false.
> >
> > Add (since: 8.0)
>
> Ack.
>
> [...]
>
> Thanks,
> Daniel



-- 
Marc-André Lureau



reply via email to

[Prev in Thread] Current Thread [Next in Thread]