| 231 | static void* newStackAddr; |
| 232 | |
| 233 | extern "C" pid_t |
| 234 | vfork() |
| 235 | { |
| 236 | JTRACE("Simulating vfork with fork"); |
| 237 | return fork(); |
| 238 | |
| 239 | char dummy; |
| 240 | static __typeof__(&vfork) vforkPtr = |
| 241 | (__typeof__(&vfork)) dmtcp_dlsym(RTLD_NEXT, "vfork"); |
| 242 | |
| 243 | JASSERT (!isPerformingCkptRestart()); |
| 244 | |
| 245 | ThreadSync::presuspendEventHookLockLock(); |
| 246 | |
| 247 | /* Acquire all locks here. */ |
| 248 | ThreadSync::acquireLocks(); |
| 249 | |
| 250 | ThreadList::vforkSuspendThreads(); |
| 251 | |
| 252 | PluginManager::eventHook(DMTCP_EVENT_VFORK_PREPARE, NULL); |
| 253 | |
| 254 | // Save the contents of the current call frame before calling libc:vfork. The |
| 255 | // vfork syscall won't return in the parent until the child process has either |
| 256 | // exited or exec'd. In both cases, the current call frame on stack will |
| 257 | // most-likely get overwritten by the child process. (The call frames below |
| 258 | // the current call-frame are expected to be safe as the child process is not |
| 259 | // expected to return from the current call frame). |
| 260 | // Failure to restore the current call frame in the parent might result in |
| 261 | // lost $RBP data that include the return address. |
| 262 | // |
| 263 | // NOTE: The vfork wrapper in pid_miscwrappers.cpp performs similar |
| 264 | // save/restore of the current call frame. This duplication is required in |
| 265 | // case we decide to not use the PID plugin. |
| 266 | // |
| 267 | // TODO: Deduplicate stack save/restore with similar code in |
| 268 | // execwrappers.cpp's vfork wrapper. |
| 269 | stackStart = &dummy; |
| 270 | // Return address is stored at $rbp + sizeof($rbp) + sizeof(void*) |
| 271 | stackSize = |
| 272 | (char*) __builtin_frame_address(0) + (2 * sizeof(void*)) - stackStart; |
| 273 | newStackAddr = JALLOC_MALLOC(stackSize); |
| 274 | JASSERT(newStackAddr); |
| 275 | memcpy(newStackAddr, stackStart, stackSize); |
| 276 | |
| 277 | vforkPid = vforkPtr(); |
| 278 | |
| 279 | // Restore parent stack. |
| 280 | if (vforkPid > 0) { |
| 281 | memcpy(stackStart, newStackAddr, stackSize); |
| 282 | JALLOC_FREE(newStackAddr); |
| 283 | } |
| 284 | |
| 285 | ThreadSync::resetLocks(false); |
| 286 | |
| 287 | if (vforkPid == -1) { |
| 288 | PluginManager::eventHook(DMTCP_EVENT_VFORK_FAILED, NULL); |
| 289 | JTRACE("vfork failed") (vforkPid); |
| 290 | } else if (vforkPid == 0) { /* child process */ |
no test coverage detected