MCPcopy Create free account
hub / github.com/dmtcp/dmtcp / double_fork

Function double_fork

src/ckptserializer.cpp:110–143  ·  view source on GitHub ↗

returns FORKED_PARENT, FORKED_GRANDCHILD, FORKED_CKPT_FAILED

Source from the content-addressed store, hash-verified

108
109// returns FORKED_PARENT, FORKED_GRANDCHILD, FORKED_CKPT_FAILED
110static forked_rc_t
111double_fork()
112{
113 pid_t pid;
114 // 0. This assumes SIGCHLD is already blocked. This works during checkpoint.
115 struct sigaction saved_sigchld_action;
116 // 1. Set SIGCHLD handler to trivial handler; save original SIGCHLD handler
117 // NOTE: allow_delivery_of_one_sigchld calls sigsuspend(). This is unblocked
118 // when SIGCHLD arrives, only for trivial_sigchld_action, not SIG_IGN.
119 struct sigaction trivial_sigchld_action;
120 set_trivial_sigchld_action(&trivial_sigchld_action);
121 sigaction(SIGCHLD, &trivial_sigchld_action, &saved_sigchld_action);
122 pid = _real_sys_fork();
123 JASSERT(pid >= 0)(pid); // Or could do: return FORKED_CKPT_FAILED;
124
125 if (pid > 0) {
126 // 2. Allow delivery of just one SIGCHLD (due to the child that did _exit())
127 allow_delivery_of_one_sigchld();
128
129 // 3. Next, we reap that child process (which is now a zombie).
130 JWARNING(_real_waitpid(pid, NULL, 0) != -1) (pid) (JASSERT_ERRNO);
131
132 // 4. ... and we then restore the original SIGCHLD handler
133 sigaction(SIGCHLD, &saved_sigchld_action, NULL);
134 return FORKED_CKPT_PARENT;
135 } else {
136 pid = _real_sys_fork();
137 JASSERT(pid >= 0)(pid);
138 if (pid > 0) {
139 _exit(EXIT_SUCCESS); // Child process exits, delivers SIGCHLD
140 }
141 return FORKED_CKPT_GRANDCHILD;
142 }
143}
144
145/*
146 * This function returns the fd to which the checkpoint file should be written.

Callers 2

open_ckpt_to_writeFunction · 0.85

Calls 4

sigactionClass · 0.70
_real_waitpidFunction · 0.70

Tested by 1