[CRIU] [scripts 2/2] stopexec: Stop immediately after exec()

Christopher Covington cov at codeaurora.org
Thu Nov 3 20:05:14 PDT 2016


From: Christopher Roberts <croberts at codeaurora.org>

Rewrite stopexec to ensure that the new executable image will be
loaded into memory before the process stops itself. This revised
behavior results in consistent memory mappings across different
restorations of a checkpoint taken after the process has stopped.

Also make the output more machine friendly by only writing the PID
of the stopped program to the log file.

Signed-off-by: Christopher Covington <cov at codeaurora.org>
---
 README.md  |  4 +--
 stopexec.c | 82 ++++++++++++++++++++++++++++++++++++++++----------------------
 2 files changed, 55 insertions(+), 31 deletions(-)

diff --git a/README.md b/README.md
index 2f2930c..e3c54ae 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
 # criu-scripts
-Some stupid scripts to analyze criu
+Tools to analyze criu and prepare processes for checkpointing
 
 * sat.py -- strace analyzer tool. Can show timing statistics from strace logs. See script's header comment for usage examples.
 * wwt.sh -- Who-Wrote-This script. Shows git based statistics about commits and lines of code for people or companies.
-* stopexec -- tool to stop a process before calling execve() thus making a process easily dumpable.
+* stopexec -- tool to stop a process after calling execve() thus making a process easily dumpable.
 * ptrace-wait -- tool to wait for any task to exit regardless of parent-child relations.
 * pstree\_cont -- tool to send SIGCONT to all processes in a tree
diff --git a/stopexec.c b/stopexec.c
index c85e02e..2536753 100644
--- a/stopexec.c
+++ b/stopexec.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2016 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 and only version
@@ -9,46 +9,70 @@
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  * more details.
- *
- * stopexec - Stop an application immediately prior to execution.
- *
- * Written by Christopher Covington.
  */
 
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
+#define _GNU_SOURCE // dprintf
+#include <stdlib.h> // EXIT_*
+#include <stdio.h> // printf, fprintf
+#include <string.h> // strerror
+#include <unistd.h> // fork, execvp, setsid
+#include <errno.h> // errno
+#include <fcntl.h> // open
+#include <signal.h> // kill
+#include <assert.h> // assert
+#include <sys/stat.h> // open
+#include <sys/ptrace.h> // ptrace
+#include <sys/types.h> // waitpid
+#include <sys/wait.h> // waitpid
 
 int main(int argc, char *argv[])
 {
-	int fd, err;
+	int fd;
 
 	if (argc < 3) {
 		printf("Typical usage: %s logfile -- program [args...] &\n",
-		       argv[0]);
-		return -1;
+			argv[0]);
+		return EXIT_FAILURE;
 	}
 
-	fd = open(argv[1], O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
+	fd = open(argv[1], O_TRUNC | O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
 	if (fd < 0) {
-		printf("Error opening %s.\n", argv[1]);
+		fprintf(stderr, "Error opening %s.\n", argv[1]);
 		return errno;
 	}
 
-	/* Set session ID to make process easily `criu dump`-able */
-	setsid();
-	dprintf(fd, "Stopping pid %d before exec().\n", getpid());
-	raise(SIGSTOP);
-
-	/* Run application */
-	execvp(argv[3], &argv[3]);
-	err = errno;
-
-	/* Log and return error if execvp failed */
-	dprintf(fd, "Error executing binary: %s (errno: %d)\n", strerror(err), err);
-	close(fd);
-	return err;
+	pid_t pid = fork();
+	if (pid) {
+		int status;
+		waitpid(pid, &status, 0);
+		/* Wait until child has stopped to write its PID so it can act
+		   as barrier of sorts. */
+		dprintf(fd, "%d", pid);
+		close(fd);
+		if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) {
+			ptrace(PTRACE_DETACH, pid, 0, SIGSTOP);
+			return EXIT_SUCCESS;
+		} else {
+			fprintf(stderr, "Child stopped unexpectedly\n");
+			kill(pid, SIGKILL);
+			return EXIT_FAILURE;
+		}
+	} else {
+		close(fd);
+		/* Set session ID to make process easily `criu dump`-able */
+		setsid();
+		int status = ptrace(PTRACE_TRACEME, 0, 0, 0);
+		if (status == -1) {
+			fprintf(stderr, "Trace request failed with error: %s\n",
+				strerror(errno));
+			return EXIT_FAILURE;
+		}
+		status = execvp(argv[3], &argv[3]);
+		if (status == -1) {
+			fprintf(stderr, "Exec of %s failed with error: %s\n",
+				argv[3], strerror(errno));
+		}
+		return EXIT_FAILURE;
+	}
+	return EXIT_SUCCESS;
 }
-- 
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code Aurora
Forum, a Linux Foundation Collaborative Project.



More information about the CRIU mailing list