From: Roman Bogorodskiy <bogorodskiy@gmail.com>
To: Brad Smith <brad@comstyle.com>
Cc: Michael Roth <michael.roth@amd.com>,
Kostiantyn Kostiuk <kkostiuk@redhat.com>,
qemu-devel@nongnu.org
Subject: Re: [PATCH] qga: fix crash when a signal arrives during shutdown
Date: Sat, 31 Oct 2026 13:49:02 +0100 [thread overview]
Message-ID: <auXjvuRiFvkCxkAN@tulp> (raw)
In-Reply-To: <auU_X4KYujIpR2Qo@humpty.home.comstyle.com>
Brad Smith wrote:
> qga: fix crash when a signal arrives during shutdown
For some reason your commit message bodies duplicate the title.
> quit_handler() stays installed for SIGINT and SIGTERM for the life
> of the process and dereferences the global ga_state. cleanup_agent()
> frees the agent state and clears ga_state, so a SIGINT or SIGTERM
> arriving after cleanup makes quit_handler() dereference NULL in
> ga_is_frozen() and the agent crashes with SIGSEGV.
>
> This happens in practice when qemu-ga runs under something that
> forwards signals. For example, running it under sudo and stopping it
> with "pkill -f" signals both sudo and qemu-ga, so the agent receives
> SIGTERM twice.
>
> Reproduced on FreeBSD by sending SIGTERM after cleanup_agent() under
> lldb.
>
> Return early from quit_handler() when ga_state is NULL, and clear
> ga_state as soon as the command state cleanup is done, before the
> main loop and the state are freed, so a signal during the rest of
> cleanup does not touch freed memory. ga_state cannot be cleared
> earlier, as command cleanup callbacks such as
> guest_fsfreeze_cleanup() still use it.
>
> Signed-off-by: Brad Smith <brad@comstyle.com>
> ---
> qga/main.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/qga/main.c b/qga/main.c
> index fd19c7037d..8cc9810572 100644
> --- a/qga/main.c
> +++ b/qga/main.c
> @@ -167,6 +167,10 @@ init_dfl_pathnames(void)
>
> static void quit_handler(int sig)
> {
> + if (!ga_state) {
> + return;
> + }
> +
> /* if we're frozen, don't exit unless we're absolutely forced to,
> * because it's basically impossible for graceful exit to complete
> * unless all log/pid files are on unfreezable filesystems. there's
> @@ -1589,13 +1593,13 @@ static void cleanup_agent(GAState *s)
> ga_command_state_free(s->command_state);
> json_message_parser_destroy(&s->parser);
> }
> + ga_state = NULL;
> g_free(s->pstate_filepath);
> g_free(s->state_filepath_isfrozen);
> if (s->main_loop) {
> g_main_loop_unref(s->main_loop);
> }
> g_free(s);
> - ga_state = NULL;
> }
>
> static int run_agent_once(GAState *s)
> --
> 2.56.0
>
I was testing this change by sending SIGTERM in a loop and noticed that
it still crashes with SIGSEGV or SIGARBT from time to time. I was able
to fix that by ignoring signals in the clean up routines:
diff --git a/qga/main.c b/qga/main.c
index 8cc9810572..47686bca80 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -167,6 +167,12 @@ init_dfl_pathnames(void)
static void quit_handler(int sig)
{
+#ifndef _WIN32
+ struct sigaction action = {
+ .sa_handler = SIG_IGN,
+ };
+#endif
+
if (!ga_state) {
return;
}
@@ -203,6 +209,13 @@ static void quit_handler(int sig)
return;
#endif
}
+
+#ifndef _WIN32
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGINT, &action, NULL);
+ sigaction(SIGTERM, &action, NULL);
+#endif
+
g_debug("received signal num %d, quitting", sig);
stop_agent(ga_state, true);
@@ -1587,6 +1600,18 @@ static void cleanup_agent(GAState *s)
if (s->load_avg_pdh_query) {
PdhCloseQuery(s->load_avg_pdh_query);
}
+#else
+ struct sigaction action = {
+ .sa_handler = SIG_IGN,
+ };
+
+ sigemptyset(&action.sa_mask);
+ if (sigaction(SIGINT, &action, NULL) != 0) {
+ g_warning("error configuring signal handler: %s", strerror(errno));
+ }
+ if (sigaction(SIGTERM, &action, NULL) != 0) {
+ g_warning("error configuring signal handler: %s", strerror(errno));
+ }
#endif
if (s->command_state) {
ga_command_state_cleanup_all(s->command_state);
prev parent reply other threads:[~2026-10-31 12:50 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-31 1:07 [PATCH] qga: fix crash when a signal arrives during shutdown Brad Smith
2026-10-31 12:49 ` Roman Bogorodskiy [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=auXjvuRiFvkCxkAN@tulp \
--to=bogorodskiy@gmail.com \
--cc=brad@comstyle.com \
--cc=kkostiuk@redhat.com \
--cc=michael.roth@amd.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.