File: nocheckpoint.c

package info (click to toggle)
dmtcp 2.6.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 6,496 kB
  • sloc: cpp: 33,592; ansic: 28,099; sh: 6,735; makefile: 1,950; perl: 1,690; python: 1,241; asm: 138; java: 13
file content (95 lines) | stat: -rw-r--r-- 2,623 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <assert.h>

// This program will be called as "nocheckpoint"
//   and its child will be called as "nocheckpoint --called-as-nocheckpoint"

#define NOCHECKPOINT_FLAG "--called-as-nocheckpoint"
#define NOCHECKPOINT_USER_PRELOAD \
        "--called-as-nocheckpoint-with-user-LD_PRELOAD"

static void call_self_nocheckpoint(char *program);
static void kill_parent();

int main(int argc, char *argv[]) {
  char *preload = getenv("LD_PRELOAD");
  if (argv[1] && strcmp(argv[1], NOCHECKPOINT_FLAG) == 0) {
    // If dmtcp_nocheckpoint failed to pass on exactly user's LD_PRELOAD
    if (preload && strlen(preload) > 0) {
      kill_parent();
    }
    return 0;
  }

  if (argv[1] && strcmp(argv[1], NOCHECKPOINT_USER_PRELOAD) == 0) {
    // If dmtcp_nocheckpoint failed to pass on exactly user's LD_PRELOAD
    if ( preload == NULL || strcmp(preload,"USER_STRING") != 0) {
      kill_parent();
    }
    return 0;
  }

  struct timespec tenth_second;
  tenth_second.tv_sec = 0;
  tenth_second.tv_nsec = 100000000; /* 100,000,000 */
  int i = 0;
  while (1) {
    unsetenv("LD_PRELOAD");
    call_self_nocheckpoint(argv[0]);

    setenv("LD_PRELOAD", "", 1);
    call_self_nocheckpoint(argv[0]);

    setenv("LD_PRELOAD", "USER_STRING", 1);
    call_self_nocheckpoint(argv[0]);

    nanosleep(&tenth_second, NULL);
    if (++i % 20 == 0) {
      printf("%2d ", i/20);
      fflush(stdout);
    }
  }
  return 0;
}

static void kill_parent() {
  char kill_command[100];
  snprintf(kill_command, sizeof(kill_command),
           "kill -9 %ld", (long)getppid());
  assert(system(kill_command) == 0);
}

static void call_self_nocheckpoint(char *program) {
  char no_checkpoint_prog[1000] = "bin/dmtcp_nocheckpoint";
  char *args[] = {NULL, NULL, NOCHECKPOINT_FLAG, NULL};
  args[0] = no_checkpoint_prog;
  args[1] = program; // Call this program, but with NOCHECKPOINT_FLAG

  int index = 0;
  int slash = -1;
  for (index = 0; index < strlen(program) && program[index] != '\0'; index++) {
    if (program[index] == '/') {
      slash = index;
    }
  }
  if (slash >= 0) {
    strncpy(no_checkpoint_prog, program, 900);
    strncpy(no_checkpoint_prog + slash + 1, "../bin/dmtcp_nocheckpoint", 900);
    // NOTE:  We already set:  args[0] = no_checkpoint_prog
  }

  int childpid = fork();
  if (childpid > 0) {
    waitpid(childpid, NULL, 0);
  } else {
    close(2); // Loader may print to stderr abbout LD_PRELOAD not found.
    execvp(args[0], args);
    perror("execvp");
  }
}