mirror of
git://git.proxmox.com/git/qemu-server.git
synced 2024-12-22 13:34:06 +03:00
0a1641aee5
currently, the 'forced_cleanup' (sending SIGKILL to the qemu process), is intended to be triggered 5 seconds after sending the initial shutdown signal (SIGTERM) which is sadly not enough for some setups. Accidentally, it could be triggered earlier than 5 seconds, if a SIGALRM triggers in the timespan directly before setting it again. Also, this approach means that depending on when machines are shutdown their forced cleanup may happen after 5 seconds, or any time after, if new vms are shut off in the meantime. Improve this situation by reworking the way we deal with this cleanup. We save the pidfd, time incl. timeout in the Client, and set a timeout to 'epoll_wait' of 10 seconds, which will then trigger a forced_cleanup. Remove entries from the forced_cleanup list when that entry is killed, or when the normal cleanup took place. To improve the shutdown behaviour, increase the default timeout to 60 seconds, which should be enough, but add a commandline toggle where users can set it to a different value. Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
98 lines
2.2 KiB
C
98 lines
2.2 KiB
C
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
/*
|
|
Copyright (C) 2018 - 2021 Proxmox Server Solutions GmbH
|
|
|
|
Author: Dominik Csapak <d.csapak@proxmox.com>
|
|
Author: Stefan Reiter <s.reiter@proxmox.com>
|
|
*/
|
|
|
|
#include <sys/syscall.h>
|
|
#include <time.h>
|
|
|
|
#ifndef __NR_pidfd_open
|
|
#define __NR_pidfd_open 434
|
|
#endif
|
|
#ifndef __NR_pidfd_send_signal
|
|
#define __NR_pidfd_send_signal 424
|
|
#endif
|
|
|
|
#define VERBOSE_PRINT(...) do { if (verbose) { printf(__VA_ARGS__); fflush(stdout); } } while (0)
|
|
|
|
static inline void log_neg(int errval, const char *msg)
|
|
{
|
|
if (errval < 0) {
|
|
perror(msg);
|
|
}
|
|
}
|
|
|
|
static inline void bail_neg(int errval, const char *msg)
|
|
{
|
|
if (errval < 0) {
|
|
perror(msg);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
static inline int
|
|
pidfd_open(pid_t pid, unsigned int flags)
|
|
{
|
|
return syscall(__NR_pidfd_open, pid, flags);
|
|
}
|
|
|
|
static inline int
|
|
pidfd_send_signal(int pidfd, int sig, siginfo_t *info, unsigned int flags)
|
|
{
|
|
return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
|
|
}
|
|
|
|
typedef enum {
|
|
CLIENT_NONE,
|
|
CLIENT_QEMU,
|
|
CLIENT_VZDUMP
|
|
} ClientType;
|
|
|
|
typedef enum {
|
|
STATE_HANDSHAKE,
|
|
STATE_IDLE,
|
|
STATE_EXPECT_STATUS_RESP,
|
|
STATE_TERMINATING
|
|
} ClientState;
|
|
|
|
struct Client {
|
|
char buf[4096];
|
|
unsigned int buflen;
|
|
|
|
int fd;
|
|
pid_t pid;
|
|
int pidfd;
|
|
time_t timeout;
|
|
|
|
ClientType type;
|
|
ClientState state;
|
|
|
|
// only relevant for type=CLIENT_QEMU
|
|
struct {
|
|
char vmid[16];
|
|
unsigned short graceful;
|
|
unsigned short guest;
|
|
bool term_check_queued;
|
|
bool backup;
|
|
} qemu;
|
|
|
|
// only relevant for type=CLIENT_VZDUMP
|
|
struct {
|
|
// vmid of referenced backup
|
|
char vmid[16];
|
|
} vzdump;
|
|
};
|
|
|
|
void handle_qmp_handshake(struct Client *client);
|
|
void handle_qmp_event(struct Client *client, struct json_object *obj);
|
|
void handle_qmp_return(struct Client *client, struct json_object *data, bool error);
|
|
void handle_vzdump_handshake(struct Client *client, struct json_object *data);
|
|
void handle_client(struct Client *client);
|
|
void add_new_client(int client_fd);
|
|
void cleanup_client(struct Client *client);
|
|
void terminate_client(struct Client *client);
|
|
void terminate_check(struct Client *client);
|