spfs: Main process wakes and kills its children on exit

Submitted by Kirill Tkhai on Jan. 18, 2018, 2:13 p.m.

Details

Message ID 151628439343.25581.14206190795893482047.stgit@localhost.localdomain
State New
Series "spfs: Main process wakes and kills its children on exit"
Headers show

Commit Message

Kirill Tkhai Jan. 18, 2018, 2:13 p.m.
Stanislav Kinsburskiy says:

"SPFS manager has a special "--exit-with-spfs" options, which is used by CRIU.
 The idea of the option is simple: force SPFS manager to exit, when it has some
 SPFS processes among its children (i.e. spfs was mounted at least once),
 but all these processes have exited for whatever reason (which usually happens
 when restore has failed and spfs mounts where unmounted).
 Although it works in overall (main SPFS manager process exits), its children
 (responsible to SPFS replacement) may wait on FUTEX for "release" command
 for corresponding SPFS mount and thus never stop until they are killed".

The patch makes the thing and kills all process group on exit.
This does not act on normal exit, as spfs main process is the
only process than, and it does not kill itself, because as kill() is
called from signal handler right before exit().

https://jira.sw.ru/browse/PSBM-80055

Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
---
 manager/context.c |    8 ++++++++
 manager/context.h |    1 +
 manager/main.c    |    5 +++++
 3 files changed, 14 insertions(+)

Patch hide | download patch | download mbox

diff --git a/manager/context.c b/manager/context.c
index 1eb37c9..7097ff0 100644
--- a/manager/context.c
+++ b/manager/context.c
@@ -64,6 +64,13 @@  static void cleanup_spfs_mount(struct spfs_manager_context_s *ctx,
 	close_namespaces(info->ns_fds);
 }
 
+static void kill_spfs_pgrp(struct spfs_manager_context_s *ctx)
+{
+	pid_t pgid = ctx->spfs_pgid;
+	if (kill(-pgid, SIGKILL))
+		pr_perror("Can't force process group to exit");
+}
+
 static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
 {
 	struct spfs_manager_context_s *ctx = &spfs_manager_context;
@@ -95,6 +102,7 @@  static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
 				cleanup_spfs_mount(ctx, info, status);
 				if (list_empty(&ctx->spfs_mounts->list) && ctx->exit_with_spfs) {
 					pr_info("spfs list is empty. Exiting.\n");
+					kill_spfs_pgrp(ctx);
 					exit(0);
 				}
 			}
diff --git a/manager/context.h b/manager/context.h
index a307803..0d994c9 100644
--- a/manager/context.h
+++ b/manager/context.h
@@ -13,6 +13,7 @@  struct spfs_manager_context_s {
 	char	*log_file;
 	char	*socket_path;
 	int	verbosity;
+	pid_t	spfs_pgid;
 	bool	daemonize;
 	bool	exit_with_spfs;
 	char	*ovz_id;
diff --git a/manager/main.c b/manager/main.c
index d3c7aaf..e490842 100644
--- a/manager/main.c
+++ b/manager/main.c
@@ -34,6 +34,11 @@  int main(int argc, char *argv[])
 			return -errno;
 		}
 	}
+	ctx->spfs_pgid = getpid();
+	if (getpgrp() != ctx->spfs_pgid && setpgrp() != 0) {
+		pr_perror("Can't set pgid");
+		return -errno;
+	}
 
 	return unreliable_socket_loop(ctx->sock, ctx, false, spfs_manager_packet_handler);
 }