* [PATCH v2 0/3] qga: Add optional `merge-output` flag to guest-exec QAPI
@ 2023-02-28 18:50 Daniel Xu
2023-02-28 18:50 ` [PATCH v2 1/3] crypto/luks: Initialize stack variable to silence warning Daniel Xu
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Daniel Xu @ 2023-02-28 18:50 UTC (permalink / raw)
To: qemu-devel; +Cc: marcandre.lureau
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 patchset adds support for merging stderr and stdout output streams
via a new QAPI flag.
Changes from v1:
* Drop invalid test fix
* Do not support `merge-output` on windows guests
* Fix a UAF in tests
Daniel Xu (3):
crypto/luks: Initialize stack variable to silence warning
qga: Add optional `merge-output` flag to guest-exec qapi
qga: test: Add tests for `merge-output` flag
crypto/block-luks.c | 2 +-
qga/commands.c | 14 ++++-
qga/qapi-schema.json | 6 +-
tests/unit/test-qga.c | 133 ++++++++++++++++++++++++++++++++++++------
4 files changed, 134 insertions(+), 21 deletions(-)
--
2.39.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2 1/3] crypto/luks: Initialize stack variable to silence warning
2023-02-28 18:50 [PATCH v2 0/3] qga: Add optional `merge-output` flag to guest-exec QAPI Daniel Xu
@ 2023-02-28 18:50 ` Daniel Xu
2023-02-28 18:50 ` [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi Daniel Xu
2023-02-28 18:50 ` [PATCH v2 3/3] qga: test: Add tests for `merge-output` flag Daniel Xu
2 siblings, 0 replies; 6+ messages in thread
From: Daniel Xu @ 2023-02-28 18:50 UTC (permalink / raw)
To: Daniel P. Berrangé, marcandre.lureau; +Cc: qemu-devel
With `../configure --enable-sanitizers`, I was getting the following
build error:
In file included from /usr/include/string.h:535,
from /home/dxu/dev/qemu/include/qemu/osdep.h:99,
from ../crypto/block-luks.c:21:
In function ‘memset’,
inlined from ‘qcrypto_block_luks_store_key’ at ../crypto/block-luks.c:843:9:
/usr/include/bits/string_fortified.h:59:10: error: ‘splitkeylen’ may be used
uninitialized [-Werror=maybe-uninitialized]
59 | return __builtin___memset_chk (__dest, __ch, __len,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
60 | __glibc_objsize0 (__dest));
| ~~~~~~~~~~~~~~~~~~~~~~~~~~
../crypto/block-luks.c: In function ‘qcrypto_block_luks_store_key’:
../crypto/block-luks.c:699:12: note: ‘splitkeylen’ was declared here
699 | size_t splitkeylen;
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
The function is actually correct -- in the cleanup branch `splitkeylen`
usage is guarded by checking `splitkey` nullness. But the compiler is
not smart enough to realize that.
Fix warning by initializing the variable.
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
crypto/block-luks.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 5688783ab1..bfdef25c80 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -696,7 +696,7 @@ qcrypto_block_luks_store_key(QCryptoBlock *block,
QCryptoBlockLUKS *luks = block->opaque;
QCryptoBlockLUKSKeySlot *slot;
g_autofree uint8_t *splitkey = NULL;
- size_t splitkeylen;
+ size_t splitkeylen = 0;
g_autofree uint8_t *slotkey = NULL;
g_autoptr(QCryptoCipher) cipher = NULL;
g_autoptr(QCryptoIVGen) ivgen = NULL;
--
2.39.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi
2023-02-28 18:50 [PATCH v2 0/3] qga: Add optional `merge-output` flag to guest-exec QAPI Daniel Xu
2023-02-28 18:50 ` [PATCH v2 1/3] crypto/luks: Initialize stack variable to silence warning Daniel Xu
@ 2023-02-28 18:50 ` Daniel Xu
2023-02-28 19:26 ` Marc-André Lureau
2023-02-28 18:50 ` [PATCH v2 3/3] qga: test: Add tests for `merge-output` flag Daniel Xu
2 siblings, 1 reply; 6+ messages in thread
From: Daniel Xu @ 2023-02-28 18:50 UTC (permalink / raw)
To: kkostiuk, michael.roth, marcandre.lureau; +Cc: qemu-devel
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 | 14 ++++++++++++--
qga/qapi-schema.json | 6 +++++-
2 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/qga/commands.c b/qga/commands.c
index 172826f8f8..e13a8e86df 100644
--- a/qga/commands.c
+++ b/qga/commands.c
@@ -270,12 +270,20 @@ static void guest_exec_child_watch(GPid pid, gint status, gpointer data)
g_spawn_close_pid(pid);
}
-/** Reset ignored signals back to default. */
static void guest_exec_task_setup(gpointer data)
{
#if !defined(G_OS_WIN32)
+ bool has_merge = *(bool *)data;
struct sigaction sigact;
+ if (has_merge) {
+ if (dup2(STDOUT_FILENO, STDERR_FILENO) != 0) {
+ slog("dup2() failed to merge stderr into stdout: %s",
+ strerror(errno));
+ }
+ }
+
+ /* Reset ignored signals back to default. */
memset(&sigact, 0, sizeof(struct sigaction));
sigact.sa_handler = SIG_DFL;
@@ -384,6 +392,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;
@@ -397,6 +406,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;
@@ -420,7 +430,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..9c2367acdf 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.
+# not effective on windows guests. defaults to false. (since 8.0)
#
# Returns: PID on success.
#
@@ -1218,7 +1221,8 @@
##
{ 'command': 'guest-exec',
'data': { 'path': 'str', '*arg': ['str'], '*env': ['str'],
- '*input-data': 'str', '*capture-output': 'bool' },
+ '*input-data': 'str', '*capture-output': 'bool',
+ '*merge-output': 'bool' },
'returns': 'GuestExec' }
--
2.39.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v2 3/3] qga: test: Add tests for `merge-output` flag
2023-02-28 18:50 [PATCH v2 0/3] qga: Add optional `merge-output` flag to guest-exec QAPI Daniel Xu
2023-02-28 18:50 ` [PATCH v2 1/3] crypto/luks: Initialize stack variable to silence warning Daniel Xu
2023-02-28 18:50 ` [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi Daniel Xu
@ 2023-02-28 18:50 ` Daniel Xu
2 siblings, 0 replies; 6+ messages in thread
From: Daniel Xu @ 2023-02-28 18:50 UTC (permalink / raw)
To: kkostiuk, michael.roth, marcandre.lureau; +Cc: qemu-devel
This commit adds a test to ensure `merge-output` functions as expected.
We also add a negative test to ensure we haven't regressed previous
functionality.
Signed-off-by: Daniel Xu <dxu@dxuuu.xyz>
---
tests/unit/test-qga.c | 133 ++++++++++++++++++++++++++++++++++++------
1 file changed, 116 insertions(+), 17 deletions(-)
diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c
index b4e0a14573..02eb4bf980 100644
--- a/tests/unit/test-qga.c
+++ b/tests/unit/test-qga.c
@@ -755,6 +755,31 @@ static void test_qga_fsfreeze_status(gconstpointer fix)
g_assert_cmpstr(status, ==, "thawed");
}
+static QDict *wait_for_guest_exec_completion(int fd, int64_t pid)
+{
+ QDict *ret = NULL;
+ int64_t now;
+ bool exited;
+ QDict *val;
+
+ now = g_get_monotonic_time();
+ do {
+ ret = qmp_fd(fd,
+ "{'execute': 'guest-exec-status',"
+ " 'arguments': { 'pid': %" PRId64 " } }", pid);
+ g_assert_nonnull(ret);
+ val = qdict_get_qdict(ret, "return");
+ exited = qdict_get_bool(val, "exited");
+ if (!exited) {
+ qobject_unref(ret);
+ }
+ } while (!exited &&
+ g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND);
+ g_assert(exited);
+
+ return ret;
+}
+
static void test_qga_guest_exec(gconstpointer fix)
{
const TestFixture *fixture = fix;
@@ -762,9 +787,8 @@ static void test_qga_guest_exec(gconstpointer fix)
QDict *val;
const gchar *out;
g_autofree guchar *decoded = NULL;
- int64_t pid, now, exitcode;
+ int64_t pid, exitcode;
gsize len;
- bool exited;
/* exec 'echo foo bar' */
ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
@@ -777,23 +801,10 @@ static void test_qga_guest_exec(gconstpointer fix)
g_assert_cmpint(pid, >, 0);
qobject_unref(ret);
- /* wait for completion */
- now = g_get_monotonic_time();
- do {
- ret = qmp_fd(fixture->fd,
- "{'execute': 'guest-exec-status',"
- " 'arguments': { 'pid': %" PRId64 " } }", pid);
- g_assert_nonnull(ret);
- val = qdict_get_qdict(ret, "return");
- exited = qdict_get_bool(val, "exited");
- if (!exited) {
- qobject_unref(ret);
- }
- } while (!exited &&
- g_get_monotonic_time() < now + 5 * G_TIME_SPAN_SECOND);
- g_assert(exited);
+ ret = wait_for_guest_exec_completion(fixture->fd, pid);
/* check stdout */
+ val = qdict_get_qdict(ret, "return");
exitcode = qdict_get_int(val, "exitcode");
g_assert_cmpint(exitcode, ==, 0);
out = qdict_get_str(val, "out-data");
@@ -802,6 +813,90 @@ static void test_qga_guest_exec(gconstpointer fix)
g_assert_cmpstr((char *)decoded, ==, "\" test_str \"");
}
+static void test_qga_guest_exec_output_no_merge(gconstpointer fix)
+{
+ const TestFixture *fixture = fix;
+ g_autoptr(QDict) ret = NULL;
+ QDict *val;
+ const gchar *out, *err;
+ g_autofree guchar *out_decoded = NULL;
+ g_autofree guchar *err_decoded = NULL;
+ int64_t pid, exitcode;
+ gsize len;
+
+ /* exec 'echo foo bar' */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
+ " 'path': '/bin/bash',"
+ " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 )); then echo stdout; else echo stderr 1>&2; fi; done;' ],"
+ " 'capture-output': true } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ val = qdict_get_qdict(ret, "return");
+ pid = qdict_get_int(val, "pid");
+ g_assert_cmpint(pid, >, 0);
+ qobject_unref(ret);
+
+ ret = wait_for_guest_exec_completion(fixture->fd, pid);
+
+ val = qdict_get_qdict(ret, "return");
+ exitcode = qdict_get_int(val, "exitcode");
+ g_assert_cmpint(exitcode, ==, 0);
+
+ /* check stdout */
+ out = qdict_get_str(val, "out-data");
+ out_decoded = g_base64_decode(out, &len);
+ g_assert_cmpint(len, ==, 14);
+ g_assert_cmpstr((char *)out_decoded, ==, "stdout\nstdout\n");
+
+ /* check stderr */
+ err = qdict_get_try_str(val, "err-data");
+ err_decoded = g_base64_decode(err, &len);
+ g_assert_cmpint(len, ==, 14);
+ g_assert_cmpstr((char *)err_decoded, ==, "stderr\nstderr\n");
+}
+
+static void test_qga_guest_exec_output_merge(gconstpointer fix)
+{
+#if !defined(G_OS_WIN32)
+ const TestFixture *fixture = fix;
+ g_autoptr(QDict) ret = NULL;
+ QDict *val;
+ const gchar *out, *err;
+ g_autofree guchar *decoded = NULL;
+ int64_t pid, exitcode;
+ gsize len;
+
+ /* exec 'echo foo bar' */
+ ret = qmp_fd(fixture->fd, "{'execute': 'guest-exec', 'arguments': {"
+ " 'path': '/bin/bash',"
+ " 'arg': [ '-c', 'for i in $(seq 4); do if (( $i %% 2 )); then echo stdout; else echo stderr 1>&2; fi; done;' ],"
+ " 'capture-output': true,"
+ " 'merge-output': true } }");
+ g_assert_nonnull(ret);
+ qmp_assert_no_error(ret);
+ val = qdict_get_qdict(ret, "return");
+ pid = qdict_get_int(val, "pid");
+ g_assert_cmpint(pid, >, 0);
+ qobject_unref(ret);
+
+ ret = wait_for_guest_exec_completion(fixture->fd, pid);
+
+ val = qdict_get_qdict(ret, "return");
+ exitcode = qdict_get_int(val, "exitcode");
+ g_assert_cmpint(exitcode, ==, 0);
+
+ /* check stdout */
+ out = qdict_get_str(val, "out-data");
+ decoded = g_base64_decode(out, &len);
+ g_assert_cmpint(len, ==, 28);
+ g_assert_cmpstr((char *)decoded, ==, "stdout\nstderr\nstdout\nstderr\n");
+
+ /* check stderr */
+ err = qdict_get_try_str(val, "err-data");
+ g_assert_null(err);
+#endif
+}
+
static void test_qga_guest_exec_invalid(gconstpointer fix)
{
const TestFixture *fixture = fix;
@@ -972,6 +1067,10 @@ int main(int argc, char **argv)
g_test_add_data_func("/qga/blockedrpcs", NULL, test_qga_blockedrpcs);
g_test_add_data_func("/qga/config", NULL, test_qga_config);
g_test_add_data_func("/qga/guest-exec", &fix, test_qga_guest_exec);
+ g_test_add_data_func("/qga/guest-exec-output-no-merge", &fix,
+ test_qga_guest_exec_output_no_merge);
+ g_test_add_data_func("/qga/guest-exec-output-merge", &fix,
+ test_qga_guest_exec_output_merge);
g_test_add_data_func("/qga/guest-exec-invalid", &fix,
test_qga_guest_exec_invalid);
g_test_add_data_func("/qga/guest-get-osinfo", &fix,
--
2.39.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi
2023-02-28 18:50 ` [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi Daniel Xu
@ 2023-02-28 19:26 ` Marc-André Lureau
2023-02-28 20:31 ` Daniel Xu
0 siblings, 1 reply; 6+ messages in thread
From: Marc-André Lureau @ 2023-02-28 19:26 UTC (permalink / raw)
To: Daniel Xu; +Cc: kkostiuk, michael.roth, qemu-devel
Hi
On Tue, Feb 28, 2023 at 10:51 PM 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 | 14 ++++++++++++--
> qga/qapi-schema.json | 6 +++++-
> 2 files changed, 17 insertions(+), 3 deletions(-)
>
> diff --git a/qga/commands.c b/qga/commands.c
> index 172826f8f8..e13a8e86df 100644
> --- a/qga/commands.c
> +++ b/qga/commands.c
> @@ -270,12 +270,20 @@ static void guest_exec_child_watch(GPid pid, gint status, gpointer data)
> g_spawn_close_pid(pid);
> }
>
> -/** Reset ignored signals back to default. */
> static void guest_exec_task_setup(gpointer data)
> {
> #if !defined(G_OS_WIN32)
> + bool has_merge = *(bool *)data;
> struct sigaction sigact;
>
> + if (has_merge) {
> + if (dup2(STDOUT_FILENO, STDERR_FILENO) != 0) {
> + slog("dup2() failed to merge stderr into stdout: %s",
> + strerror(errno));
I would leave a FIXME comment for glib 2.58 g_spawn_async_with_fds() usage
> + }
> + }
> +
> + /* Reset ignored signals back to default. */
> memset(&sigact, 0, sizeof(struct sigaction));
> sigact.sa_handler = SIG_DFL;
>
> @@ -384,6 +392,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;
> @@ -397,6 +406,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;
>
> @@ -420,7 +430,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..9c2367acdf 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.
> +# not effective on windows guests. defaults to false. (since 8.0)
I think you should return an error on Windows instead.
> #
> # Returns: PID on success.
> #
> @@ -1218,7 +1221,8 @@
> ##
> { 'command': 'guest-exec',
> 'data': { 'path': 'str', '*arg': ['str'], '*env': ['str'],
> - '*input-data': 'str', '*capture-output': 'bool' },
> + '*input-data': 'str', '*capture-output': 'bool',
> + '*merge-output': 'bool' },
> 'returns': 'GuestExec' }
>
>
> --
> 2.39.1
>
--
Marc-André Lureau
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi
2023-02-28 19:26 ` Marc-André Lureau
@ 2023-02-28 20:31 ` Daniel Xu
0 siblings, 0 replies; 6+ messages in thread
From: Daniel Xu @ 2023-02-28 20:31 UTC (permalink / raw)
To: Marc-André Lureau; +Cc: kkostiuk, michael.roth, qemu-devel
Hi Marc-André,
Apologies if it looks like I ignored your previous email. I forgot to
renew my domain registration so all my emails were getting blackholed
or bounced for ~17 hours.
But w.r.t. fallback with old versions of glib, I think it may be a
little uglier than that. It looks like the build system uses
preprocessor macros to warn on too-new APIs. So I suppose we could
#undef and redefine GLIB_VERSION_MIN_REQUIRED, but may not be very nice.
But if you feel strongly I can try that.
On Tue, Feb 28, 2023 at 11:26:09PM +0400, Marc-André Lureau wrote:
> Hi
>
> On Tue, Feb 28, 2023 at 10:51 PM 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 | 14 ++++++++++++--
> > qga/qapi-schema.json | 6 +++++-
> > 2 files changed, 17 insertions(+), 3 deletions(-)
> >
> > diff --git a/qga/commands.c b/qga/commands.c
> > index 172826f8f8..e13a8e86df 100644
> > --- a/qga/commands.c
> > +++ b/qga/commands.c
> > @@ -270,12 +270,20 @@ static void guest_exec_child_watch(GPid pid, gint status, gpointer data)
> > g_spawn_close_pid(pid);
> > }
> >
> > -/** Reset ignored signals back to default. */
> > static void guest_exec_task_setup(gpointer data)
> > {
> > #if !defined(G_OS_WIN32)
> > + bool has_merge = *(bool *)data;
> > struct sigaction sigact;
> >
> > + if (has_merge) {
> > + if (dup2(STDOUT_FILENO, STDERR_FILENO) != 0) {
> > + slog("dup2() failed to merge stderr into stdout: %s",
> > + strerror(errno));
>
> I would leave a FIXME comment for glib 2.58 g_spawn_async_with_fds() usage
Ack.
>
> > + }
> > + }
> > +
> > + /* Reset ignored signals back to default. */
> > memset(&sigact, 0, sizeof(struct sigaction));
> > sigact.sa_handler = SIG_DFL;
> >
> > @@ -384,6 +392,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;
> > @@ -397,6 +406,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;
> >
> > @@ -420,7 +430,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..9c2367acdf 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.
> > +# not effective on windows guests. defaults to false. (since 8.0)
>
> I think you should return an error on Windows instead.
Ack.
[...]
Thanks,
Daniel
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2023-02-28 20:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-28 18:50 [PATCH v2 0/3] qga: Add optional `merge-output` flag to guest-exec QAPI Daniel Xu
2023-02-28 18:50 ` [PATCH v2 1/3] crypto/luks: Initialize stack variable to silence warning Daniel Xu
2023-02-28 18:50 ` [PATCH v2 2/3] qga: Add optional `merge-output` flag to guest-exec qapi Daniel Xu
2023-02-28 19:26 ` Marc-André Lureau
2023-02-28 20:31 ` Daniel Xu
2023-02-28 18:50 ` [PATCH v2 3/3] qga: test: Add tests for `merge-output` flag Daniel Xu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).