| | Attached (ptree2.c). I ran it as: | | $ ./ptree2 -n 1 -d 2 Now, really attached :-)
#include <stdio.h> #include <unistd.h> #include <wait.h> #include <errno.h> #include <string.h> int max_depth = 3; int num_children = 3; #define CKPT_READY "checkpoint-ready" #define CKPT_DONE "checkpoint-done" #define TEST_DONE "test-done" #define LOG_FILE "log-ptree2" #define SYS_GETGPID 1 #ifdef SYS_GETGPID static inline int sys_getgpid() { #define __NR_getgpid 335 return syscall(__NR_getgpid); } #endif FILE *logfp; void do_exit(int status) { if (logfp) { fflush(logfp); fclose(logfp); } _Exit(status); } int get_my_global_pid() { } int test_done() { int rc; rc = access(TEST_DONE, F_OK); if (rc == 0) return 1; else if (errno == ENOENT) return 0; fprintf(logfp, "access(%s) failed, %s\n", TEST_DONE, strerror(errno)); do_exit(1); } int checkpoint_done() { int rc; rc = access(CKPT_DONE, F_OK); if (rc == 0) return 1; else if (errno == ENOENT) return 0; fprintf(logfp, "access(%s) failed, %s\n", CKPT_DONE, strerror(errno)); do_exit(1); } void checkpoint_ready() { int fd; fd = creat(CKPT_READY, 0666, 0); if (fd < 0) { fprintf(logfp, "creat(%s) failed, %s\n", CKPT_READY, strerror(errno)); do_exit(1); } close(fd); } print_exit_status(int pid, int status) { fprintf(logfp, "Pid %d unexpected exit - ", pid); if (WIFEXITED(status)) { fprintf(logfp, "exit status %d\n", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { fprintf(logfp, "got signal %d\n", WTERMSIG(status)); } else { fprintf(logfp, "stopped/continued ?\n"); } } void do_wait() { int rc; int n; int status; n = 0; while(1) { rc = waitpid(-1, &status, 0); if (rc < 0) break; n++; if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) print_exit_status(rc, status); } if (errno != ECHILD) { fprintf(logfp, "waitpid(%d) failed, error %s\n", rc, strerror(errno)); do_exit(1); } if (getpid() == 1 && n != num_children * max_depth) { fprintf(logfp, "Only %d of %d children exited ?\n", num_children, num_children * max_depth); do_exit(1); } do_exit(0); } static do_child(int depth, char *suffix); create_children(int depth, char *parent_suffix) { int i; int child_pid; char suffix[1024]; for (i = 0; i < num_children; i++) { sprintf(suffix, "%s-%d", parent_suffix, i); child_pid = fork(); if (child_pid == 0) do_child(depth, suffix); else if (child_pid < 0) { fprintf(logfp, "fork() failed, depth %d, " "child %d, error %s\n", depth, i, strerror(errno)); do_exit(1); } } } do_child(int depth, char *suffix) { int i; FILE *cfp; char cfile[256]; char *mode = "w"; /* * Recursively calls do_child() and both parent and child * execute the code below */ if (depth < max_depth) create_children(depth+1, suffix); sprintf(cfile, "%s%s", LOG_FILE, suffix); i = 0; while (!test_done()) { /* truncate the first time, append after that */ cfp = fopen(cfile, mode); mode = "a"; if (!cfp) { fprintf(logfp, "fopen(%s) failed, error %s\n", cfile, strerror(errno)); do_exit(1); } fprintf(cfp, "gpid %d, pid %d: i %d\n", sys_getgpid(), getpid(), i++); fflush(cfp); sleep(1); fprintf(cfp, "gpid %d: woke up from sleep(1)\n", sys_getgpid()); fflush(cfp); fclose(cfp); } /* Wait for any children that pre-deceased us */ do_wait(); do_exit(0); } static void usage(char *argv[]) { printf("%s [h] [-d max-depth] [-n max-children]\n", argv[0]); printf("\t <max-depth> max depth of process tree, default 3\n"); printf("\t <num-children> # of children per process, default 3\n"); do_exit(1); } main(int argc, char *argv[]) { int c; int i; int status; if (test_done()) { printf("Remove %s before running test\n", TEST_DONE); do_exit(1); } while ((c = getopt(argc, argv, "hd:n:")) != EOF) { switch (c) { case 'd': max_depth = atoi(optarg); break; case 'n': num_children = atoi(optarg); break; case 'h': default: usage(argv); } }; logfp = fopen(LOG_FILE, "w"); if (!logfp) { fprintf(stderr, "fopen(%s) failed, %s\n", LOG_FILE, strerror(errno)); fflush(stderr); do_exit(1); } close(0);close(1);close(2); create_children(1, ""); /* * Now that we closed the special files and created process tree * tell any wrapper scripts, we are ready for checkpoint */ checkpoint_ready(); #if 0 while(!checkpoint_done()) sleep(1); #endif do_wait(); }
_______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers