From nobody Tue Feb 10 04:07:56 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1538910511139777.3777892885266; Sun, 7 Oct 2018 04:08:31 -0700 (PDT) Received: from localhost ([::1]:41927 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g96vB-0000qV-LZ for importer@patchew.org; Sun, 07 Oct 2018 07:08:25 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:47095) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1g96pa-00055h-GJ for qemu-devel@nongnu.org; Sun, 07 Oct 2018 07:02:39 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1g96pY-0007Q7-9O for qemu-devel@nongnu.org; Sun, 07 Oct 2018 07:02:38 -0400 Received: from mail-wr1-x42c.google.com ([2a00:1450:4864:20::42c]:33902) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1g96pW-0007PD-Pc for qemu-devel@nongnu.org; Sun, 07 Oct 2018 07:02:35 -0400 Received: by mail-wr1-x42c.google.com with SMTP id z4-v6so17740351wrb.1 for ; Sun, 07 Oct 2018 04:02:34 -0700 (PDT) Received: from bark.daynix ([141.226.163.173]) by smtp.gmail.com with ESMTPSA id v106-v6sm22065671wrc.85.2018.10.07.04.02.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 07 Oct 2018 04:02:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=daynix-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=J+jOLYhXgvu41G5QnA8GkxA8S56LZLc6TOBP8Vx0d10=; b=S8n+a5eJpG5m1rU4Bq7gF9CjrREdJ646mLXVoJhOEQrABqMRjSqUWWqv5IHxcD0Xp8 F5z8FY22Qshrp5mRGlat9LxSz+c7UPcYMXqe5uoiIdfmWnDsyub/lZp9QfIuvUJ8HYQa 3QDYq0+8F3HhJWTtlcSdf8SOOnXXvphfGHrb/cj5v8uovucMDq7NPqCoVcaXGD8VXuSq 2B9GSKVF+CAJ2mbg58ZRS+oF2lnAS9S7VBW87eF0zAnv2U8U+UbytxhE5j8NBFTXJ+eO iQNNBEqcgteoIXi8JnfV5Mx+JtlanOX5fhQtPLU9eBcyyKvhEXTZNMwEb76+0AbieUsW 2X/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=J+jOLYhXgvu41G5QnA8GkxA8S56LZLc6TOBP8Vx0d10=; b=Y+PDEDt/0NZ+gKJ7GDfRhoXdv9MzcsABfYMhCv46bzq/CZpftmMiV52avWeEsUi8jV n2yo1J/jTIHBQF2AG77vgM2/tDKkaDzvW6vPusbC+DrNTs48rzHZRn0Mup3K21TCBZSk 5stF1D7AsdDizWJMZfY50cErdq41xTQLbrpp6XGbS9FF/E4BqKQvjhTjbcu+VcA+VYOf y7491qsuY1P7//IzIIXHONPZx1VkvRau+iW/uq9lDP92Sprxi02NnYAKbF5eaIqbcsEm BMuz82CJ66ZhD948TtAq9hVN7XgH8KdjwT3rKMm71Umu4fNwQv4cUNiSJkh1yk9P77l2 UBqQ== X-Gm-Message-State: ABuFfogiCCACnAHo5HGVP4Q6DAHXv43D0Y3VI00LREAUsIfxbYXOVcKt 9SJsboU7DxRQO4NU5aC0pXDoIyvr/pM= X-Google-Smtp-Source: ACcGV61Jb0uOPhRUE8eBQ+D9d6/OH0TY6Fopy94VVAqV9bH4HOc3xZYlHAz+rzhDktXFFunPFOW8fw== X-Received: by 2002:a5d:4a86:: with SMTP id o6-v6mr14153273wrq.132.1538910153396; Sun, 07 Oct 2018 04:02:33 -0700 (PDT) From: Bishara AbuHattoum To: qemu-devel@nongnu.org, Michael Roth Date: Sun, 7 Oct 2018 14:02:20 +0300 Message-Id: <20181007110223.129692-5-bishara@daynix.com> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20181007110223.129692-1-bishara@daynix.com> References: <20181007110223.129692-1-bishara@daynix.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::42c Subject: [Qemu-devel] [PATCH v2 4/7] qga: add --retry-path option for re-initializing channel on failure X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Yan Vugenfirer , Sameeh Jubran Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Michael Roth This adds an option to instruct the agent to periodically attempt re-opening the communication channel after a channel error has occurred. The main use-case for this is providing an OS-independent way of allowing the agent to survive situations like hotplug/unplug of the communication channel, or initial guest set up where the agent may be installed/started prior to the installation of the channel device's driver. There are nicer ways of implementing this functionality via things like systemd services, but this option is useful for platforms like *BSD/w32. Currently a channel error will result in the GSource for that channel being removed from the GMainLoop, but the main loop continuing to run. That behavior results in a dead loop when --retry-path isn't set, and prevents us from knowing when to attempt re-opening the channel when it is set, so we also force the loop to exit as part of this patch. Signed-off-by: Michael Roth --- qga/main.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/qga/main.c b/qga/main.c index 23a0a46b84..f359499aaa 100644 --- a/qga/main.c +++ b/qga/main.c @@ -58,6 +58,7 @@ #endif #define QGA_SENTINEL_BYTE 0xFF #define QGA_CONF_DEFAULT CONFIG_QEMU_CONFDIR G_DIR_SEPARATOR_S "qemu-ga.co= nf" +#define QGA_RETRY_INTERVAL 5 =20 static struct { const char *state_dir; @@ -86,6 +87,7 @@ typedef struct GAConfig { int daemonize; GLogLevelFlags log_level; int dumpconf; + bool retry_path; } GAConfig; =20 struct GAState { @@ -115,6 +117,7 @@ struct GAState { GAPersistentState pstate; GAConfig *config; int socket_activation; + bool force_exit; }; =20 struct GAState *ga_state; @@ -137,6 +140,7 @@ DWORD WINAPI service_ctrl_handler(DWORD ctrl, DWORD typ= e, LPVOID data, VOID WINAPI service_main(DWORD argc, TCHAR *argv[]); #endif static int run_agent(GAState *s); +static void stop_agent(GAState *s, bool requested); =20 static void init_dfl_pathnames(void) @@ -185,9 +189,7 @@ static void quit_handler(int sig) } g_debug("received signal num %d, quitting", sig); =20 - if (g_main_loop_is_running(ga_state->main_loop)) { - g_main_loop_quit(ga_state->main_loop); - } + stop_agent(ga_state, true); } =20 #ifndef _WIN32 @@ -272,6 +274,10 @@ QEMU_COPYRIGHT "\n" " to list available RPCs)\n" " -D, --dump-conf dump a qemu-ga config file based on current config\n" " options / command-line parameters to stdout\n" +" -r, --retry-path attempt re-opening path if it's unavailable or closed= \n" +" due to an error which may be recoverable in the futur= e\n" +" (virtio-serial driver re-install, serial device hot\n" +" plug/unplug, etc.)\n" " -h, --help display this help and exit\n" "\n" QEMU_HELP_BOTTOM "\n" @@ -631,6 +637,7 @@ static gboolean channel_event_cb(GIOCondition condition= , gpointer data) switch (status) { case G_IO_STATUS_ERROR: g_warning("error reading channel"); + stop_agent(s, false); return false; case G_IO_STATUS_NORMAL: buf[count] =3D 0; @@ -974,6 +981,10 @@ static void config_load(GAConfig *config) /* enable all log levels */ config->log_level =3D G_LOG_LEVEL_MASK; } + if (g_key_file_has_key(keyfile, "general", "retry-path", NULL)) { + config->retry_path =3D + g_key_file_get_boolean(keyfile, "general", "retry-path", &gerr= ); + } if (g_key_file_has_key(keyfile, "general", "blacklist", NULL)) { config->bliststr =3D g_key_file_get_string(keyfile, "general", "blacklist", &gerr); @@ -1035,6 +1046,8 @@ static void config_dump(GAConfig *config) g_key_file_set_string(keyfile, "general", "statedir", config->state_di= r); g_key_file_set_boolean(keyfile, "general", "verbose", config->log_level =3D=3D G_LOG_LEVEL_MASK); + g_key_file_set_boolean(keyfile, "general", "retry-path", + config->retry_path); tmp =3D list_join(config->blacklist, ','); g_key_file_set_string(keyfile, "general", "blacklist", tmp); g_free(tmp); @@ -1053,7 +1066,7 @@ static void config_dump(GAConfig *config) =20 static void config_parse(GAConfig *config, int argc, char **argv) { - const char *sopt =3D "hVvdm:p:l:f:F::b:s:t:D"; + const char *sopt =3D "hVvdm:p:l:f:F::b:s:t:Dr"; int opt_ind =3D 0, ch; const struct option lopt[] =3D { { "help", 0, NULL, 'h' }, @@ -1073,6 +1086,7 @@ static void config_parse(GAConfig *config, int argc, = char **argv) { "service", 1, NULL, 's' }, #endif { "statedir", 1, NULL, 't' }, + { "retry-path", 0, NULL, 'r' }, { NULL, 0, NULL, 0 } }; =20 @@ -1117,6 +1131,9 @@ static void config_parse(GAConfig *config, int argc, = char **argv) case 'D': config->dumpconf =3D 1; break; + case 'r': + config->retry_path =3D true; + break; case 'b': { if (is_help_option(optarg)) { qmp_for_each_command(&ga_commands, ga_print_cmd, NULL); @@ -1320,9 +1337,6 @@ static void cleanup_agent(GAState *s) ga_command_state_free(s->command_state); json_message_parser_destroy(&s->parser); } - if (s->channel) { - ga_channel_free(s->channel); - } g_free(s->pstate_filepath); g_free(s->state_filepath_isfrozen); if (s->main_loop) { @@ -1332,7 +1346,7 @@ static void cleanup_agent(GAState *s) ga_state =3D NULL; } =20 -static int run_agent(GAState *s) +static int run_agent_once(GAState *s) { if (!channel_init(s, s->config->method, s->config->channel_path, s->socket_activation ? FIRST_SOCKET_ACTIVATION_FD : = -1)) { @@ -1342,9 +1356,41 @@ static int run_agent(GAState *s) =20 g_main_loop_run(ga_state->main_loop); =20 + if (s->channel) { + ga_channel_free(s->channel); + } + return EXIT_SUCCESS; } =20 +static int run_agent(GAState *s) +{ + int ret =3D EXIT_SUCCESS; + + s->force_exit =3D false; + + do { + ret =3D run_agent_once(s); + if (s->config->retry_path && !s->force_exit) { + g_warning("agent stopped unexpectedly, restarting..."); + sleep(QGA_RETRY_INTERVAL); + } + } while (s->config->retry_path && !s->force_exit); + + return ret; +} + +static void stop_agent(GAState *s, bool requested) +{ + if (!s->force_exit) { + s->force_exit =3D requested; + } + + if (g_main_loop_is_running(s->main_loop)) { + g_main_loop_quit(s->main_loop); + } +} + int main(int argc, char **argv) { int ret =3D EXIT_SUCCESS; --=20 2.17.0