From: Konstantin Kostiuk <kkostiuk@redhat.com>
To: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
Cc: qemu-devel@nongnu.org, den@virtuozzo.com, michael.roth@amd.com,
marcandre.lureau@gmail.com
Subject: Re: [PATCH 1/6] qga: Add process termination functionality
Date: Thu, 26 Oct 2023 11:24:04 +0300 [thread overview]
Message-ID: <CAPMcbCoJ94bMHat5FjXFoxfNBfaQMjcAnXUQsOV2Fbw+ovS1BQ@mail.gmail.com> (raw)
In-Reply-To: <20231025140058.113376-2-alexander.ivanov@virtuozzo.com>
[-- Attachment #1: Type: text/plain, Size: 5767 bytes --]
On Wed, Oct 25, 2023 at 5:01 PM Alexander Ivanov <
alexander.ivanov@virtuozzo.com> wrote:
> We need to terminate processes executed with guest-exec command. Add
> guest-exec-terminate command for process termination by PID.
>
> Signed-off-by: Alexander Ivanov <alexander.ivanov@virtuozzo.com>
> ---
> qga/commands-common.h | 2 ++
> qga/commands-win32.c | 64 +++++++++++++++++++++++++++++++++++++++++++
> qga/commands.c | 34 +++++++++++++++++++++++
> qga/qapi-schema.json | 13 +++++++++
> 4 files changed, 113 insertions(+)
>
> diff --git a/qga/commands-common.h b/qga/commands-common.h
> index 8c1c56aac9..34b9a22578 100644
> --- a/qga/commands-common.h
> +++ b/qga/commands-common.h
> @@ -80,4 +80,6 @@ GuestFileRead *guest_file_read_unsafe(GuestFileHandle
> *gfh,
> */
> char *qga_get_host_name(Error **errp);
>
> +int kill_process_tree(int64_t pid);
> +
> #endif
> diff --git a/qga/commands-win32.c b/qga/commands-win32.c
> index 697c65507c..5aa43a9ed7 100644
> --- a/qga/commands-win32.c
> +++ b/qga/commands-win32.c
> @@ -27,6 +27,7 @@
> #include <lm.h>
> #include <wtsapi32.h>
> #include <wininet.h>
> +#include <tlhelp32.h>
>
> #include "guest-agent-core.h"
> #include "vss-win32.h"
> @@ -2522,3 +2523,66 @@ GuestCpuStatsList *qmp_guest_get_cpustats(Error
> **errp)
> error_setg(errp, QERR_UNSUPPORTED);
> return NULL;
> }
> +
> +int kill_process_tree(int64_t pid)
> +{
> + PROCESSENTRY32 proc_entry;
> + HANDLE snapshot, process;
> + GList *pid_entry, *pid_list = NULL;
> + bool added, success;
> + int res = 0;
> +
> + snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
> + if (snapshot == INVALID_HANDLE_VALUE) {
> + return GetLastError();
> + }
> +
> + pid_list = g_list_append(pid_list, GUINT_TO_POINTER(pid));
> +
> + proc_entry.dwSize = sizeof(PROCESSENTRY32);
> + do {
> + added = false;
> + for (success = Process32First(snapshot, &proc_entry);
> + success; success = Process32Next(snapshot, &proc_entry)) {
> + gpointer ppid_p, pid_p;
> + ppid_p = GUINT_TO_POINTER(proc_entry.th32ParentProcessID);
> + pid_p = GUINT_TO_POINTER(proc_entry.th32ProcessID);
> + if (g_list_find(pid_list, ppid_p) && !g_list_find(pid_list,
> pid_p)) {
> + pid_list = g_list_append(pid_list, pid_p);
> + added = true;
> + }
> + }
> + } while (added);
>
+
> + for (success = Process32First(snapshot, &proc_entry);
> + success; success = Process32Next(snapshot, &proc_entry)) {
> + if (g_list_find(pid_list,
> GUINT_TO_POINTER(proc_entry.th32ProcessID))) {
> + g_debug("killing pid=%u ppid=%u name=%s",
> + (guint)proc_entry.th32ProcessID,
> + (guint)proc_entry.th32ParentProcessID,
> + proc_entry.szExeFile);
> + }
> + }
> +
>
Why do we need to store these processes before termination?
I understand that we need to enumerate all processes to find children
but why we can't terminate it on the fly?
> + CloseHandle(snapshot);
> +
> + for (pid_entry = pid_list; pid_entry; pid_entry = pid_entry->next) {
> + pid = GPOINTER_TO_UINT(pid_entry->data);
> + process = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
> + if (process == INVALID_HANDLE_VALUE) {
> + if (!res) {
> + res = GetLastError();
> + if (res == ERROR_FILE_NOT_FOUND) {
> + res = 0;
> + }
> + }
> + continue;
> + }
> + TerminateProcess(process, 255);
> + CloseHandle(process);
> + }
> +
> + g_list_free(pid_list);
> +
> + return res;
> +}
> diff --git a/qga/commands.c b/qga/commands.c
> index ce172edd2d..af8459c587 100644
> --- a/qga/commands.c
> +++ b/qga/commands.c
> @@ -529,6 +529,40 @@ done:
> return ge;
> }
>
> +void qmp_guest_exec_terminate(int64_t pid, Error **errp)
> +{
> + GuestExecInfo *gei;
> +
> + slog("guest-exec-terminate called, pid: %u", (uint32_t)pid);
> +
> + gei = guest_exec_info_find(pid);
> + if (gei == NULL) {
> + error_setg(errp, QERR_INVALID_PARAMETER, "pid");
> + return;
> + }
> +
> + if (gei->finished) {
> + return;
> + }
> +
> +#ifdef G_OS_WIN32
> + char buf[32];
> + int res;
> +
> + res = kill_process_tree(pid);
> + if (res != 0) {
> + snprintf(buf, sizeof(buf), "win32 err %d", res);
> + error_setg(errp, QERR_QGA_COMMAND_FAILED, buf);
> + }
> +#else
> + if (kill(pid, SIGKILL) < 0) {
> + if (errno != ESRCH) {
> + error_setg(errp, QERR_QGA_COMMAND_FAILED, strerror(errno));
> + }
> + }
> +#endif
> +}
> +
> /* Convert GuestFileWhence (either a raw integer or an enum value) into
> * the guest's SEEK_ constants. */
> int ga_parse_whence(GuestFileWhence *whence, Error **errp)
> diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json
> index 876e2a8ea8..b39be4cdc2 100644
> --- a/qga/qapi-schema.json
> +++ b/qga/qapi-schema.json
> @@ -1326,6 +1326,19 @@
> '*input-data': 'str', '*capture-output':
> 'GuestExecCaptureOutput' },
> 'returns': 'GuestExec' }
>
> +##
> +# @guest-exec-terminate:
> +#
> +# Terminate process associated with PID retrieved via guest-exec.
> +#
> +# @pid: pid returned from guest-exec
> +#
> +# Returns: Nothing on success.
> +#
> +# Since: 8.2
> +##
> +{ 'command': 'guest-exec-terminate',
> + 'data': { 'pid': 'int' } }
>
> ##
> # @GuestHostName:
> --
> 2.34.1
>
>
[-- Attachment #2: Type: text/html, Size: 7393 bytes --]
next prev parent reply other threads:[~2023-10-26 8:24 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-10-25 14:00 [PATCH 0/6] qga: Assorted patches, let us discuss Alexander Ivanov
2023-10-25 14:00 ` [PATCH 1/6] qga: Add process termination functionality Alexander Ivanov
2023-10-26 8:24 ` Konstantin Kostiuk [this message]
2023-10-25 14:00 ` [PATCH 2/6] qga: Move command execution code to a separate function Alexander Ivanov
2023-10-26 8:28 ` Konstantin Kostiuk
2023-10-25 14:00 ` [PATCH 3/6] qga: Let run_command() work without input data Alexander Ivanov
2023-10-25 14:00 ` [PATCH 4/6] qga: Add user creation functionality Alexander Ivanov
2023-10-25 14:00 ` [PATCH 5/6] qga: Add timeout for fsfreeze Alexander Ivanov
2023-10-26 9:16 ` Konstantin Kostiuk
2023-10-30 16:32 ` Alexander Ivanov
2023-10-30 17:37 ` Konstantin Kostiuk
2023-10-25 14:00 ` [PATCH 6/6] qga: Cancel async snapshot before abort Alexander Ivanov
2023-10-26 8:47 ` Konstantin Kostiuk
2023-10-26 9:17 ` Konstantin Kostiuk
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=CAPMcbCoJ94bMHat5FjXFoxfNBfaQMjcAnXUQsOV2Fbw+ovS1BQ@mail.gmail.com \
--to=kkostiuk@redhat.com \
--cc=alexander.ivanov@virtuozzo.com \
--cc=den@virtuozzo.com \
--cc=marcandre.lureau@gmail.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 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).