root/dmtcpworker.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. restoreUserLDPRELOAD
  2. determineCkptSignal
  3. dmtcp_prepare_wrappers
  4. calculateArgvAndEnvSize
  5. getLogFilePath
  6. writeCurrentLogFileNameToPrevLogFile
  7. prepareLogAndProcessdDataFromSerialFile
  8. processRlimit
  9. segFaultHandler
  10. installSegFaultHandler
  11. resetOnFork
  12. cleanupWorker
  13. interruptCkpthread
  14. ckptThreadPerformExit
  15. waitForCoordinatorMsg
  16. informCoordinatorOfRUNNINGState
  17. waitForStage1Suspend
  18. waitForStage2Checkpoint
  19. waitForStage3Refill
  20. waitForStage4Resume
  21. eventHook

   1 /****************************************************************************
   2  *   Copyright (C) 2006-2013 by Jason Ansel, Kapil Arya, and Gene Cooperman *
   3  *   jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu              *
   4  *                                                                          *
   5  *  This file is part of DMTCP.                                             *
   6  *                                                                          *
   7  *  DMTCP is free software: you can redistribute it and/or                  *
   8  *  modify it under the terms of the GNU Lesser General Public License as   *
   9  *  published by the Free Software Foundation, either version 3 of the      *
  10  *  License, or (at your option) any later version.                         *
  11  *                                                                          *
  12  *  DMTCP is distributed in the hope that it will be useful,                *
  13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of          *
  14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
  15  *  GNU Lesser General Public License for more details.                     *
  16  *                                                                          *
  17  *  You should have received a copy of the GNU Lesser General Public        *
  18  *  License along with DMTCP:dmtcp/src.  If not, see                        *
  19  *  <http://www.gnu.org/licenses/>.                                         *
  20  ****************************************************************************/
  21 
  22 #include <stdlib.h>
  23 #include <sys/time.h>
  24 #include <sys/resource.h>
  25 #include "dmtcpworker.h"
  26 #include "mtcpinterface.h"
  27 #include "threadsync.h"
  28 #include "processinfo.h"
  29 #include "syscallwrappers.h"
  30 #include "util.h"
  31 #include "syslogwrappers.h"
  32 #include "coordinatorapi.h"
  33 #include "shareddata.h"
  34 #include "threadlist.h"
  35 #include  "../jalib/jsocket.h"
  36 #include  "../jalib/jfilesystem.h"
  37 #include  "../jalib/jconvert.h"
  38 #include  "../jalib/jbuffer.h"
  39 
  40 using namespace dmtcp;
  41 
  42 LIB_PRIVATE int dmtcp_wrappers_initializing = 0;
  43 
  44 LIB_PRIVATE void pthread_atfork_prepare();
  45 LIB_PRIVATE void pthread_atfork_parent();
  46 LIB_PRIVATE void pthread_atfork_child();
  47 
  48 void pidVirt_pthread_atfork_child() __attribute__((weak));
  49 
  50 /* This is defined by newer gcc version unique for each module.  */
  51 extern void *__dso_handle __attribute__ ((__weak__,
  52                                           __visibility__ ("hidden")));
  53 
  54 EXTERNC int __register_atfork(void (*prepare)(void), void (*parent)(void),
  55                               void (*child)(void), void *dso_handle);
  56 
  57 EXTERNC void *ibv_get_device_list(void *) __attribute__((weak));
  58 
  59 /* The following instance of the DmtcpWorker is just to trigger the constructor
  60  * to allow us to hijack the process
  61  */
  62 DmtcpWorker DmtcpWorker::theInstance;
  63 bool DmtcpWorker::_exitInProgress = false;
  64 
  65 void restoreUserLDPRELOAD()
  66 {
  67   /* A call to setenv() can result in a call to malloc(). The setenv() call may
  68    * also grab a low-level libc lock before calling malloc. The malloc()
  69    * wrapper, if present, will try to acquire the wrapper lock. This can lead
  70    * to a deadlock in the following scenario:
  71    *
  72    * T1 (main thread): fork() -> acquire exclusive lock
  73    * T2 (ckpt thread): setenv() -> acquire low-level libc lock ->
  74    *                   malloc -> wait for wrapper-exec lock.
  75    * T1: setenv() -> block on low-level libc lock (held by T2).
  76    *
  77    * The simpler solution would have been to not call setenv from DMTCP, and
  78    * use putenv instead. This would require larger change.
  79    *
  80    * The solution used here is to set LD_PRELOAD to "" before * user main().
  81    * This is as good as unsetting it.  Later, the ckpt-thread * can unset it
  82    * if it is still NULL, but then there is a possibility of a race between
  83    * user code and ckpt-thread.
  84    */
  85 
  86   // We have now successfully used LD_PRELOAD to execute prior to main()
  87   // Next, hide our value of LD_PRELOAD, in a global variable.
  88   // At checkpoint and restart time, we will no longer need our LD_PRELOAD.
  89   // We will need it in only one place:
  90   //  when the user application makes an exec call:
  91   //   If anybody calls our execwrapper, we will reset LD_PRELOAD then.
  92   //   If they directly call _real_execve to get libc symbol, they will
  93   //   not be part of DMTCP computation.
  94   // This has the advantage that our value of LD_PRELOAD will always come
  95   //   before any paths set by user application.
  96   // Also, bash likes to keep its own envp, but we will interact with bash only
  97   //   within the exec wrapper.
  98   // NOTE:  If the user called exec("ssh ..."), we currently catch this in
  99   //   DmtcpWorker() due to LD_PRELOAD, unset LD_PRELOAD, and edit this into
 100   //   exec("dmtcp_launch ... ssh ..."), and re-execute.
 101   //   This way, we will unset LD_PRELOAD here and now, instead of at that time.
 102   char *preload = getenv("LD_PRELOAD");
 103   char *userPreload =  getenv(ENV_VAR_ORIG_LD_PRELOAD);
 104   preload[0] = '\0';
 105   if (userPreload == NULL) {
 106     //_dmtcp_unsetenv("LD_PRELOAD");
 107   } else {
 108     strcat(preload, userPreload);
 109     //setenv("LD_PRELOAD", userPreload, 1);
 110   }
 111   JTRACE("LD_PRELOAD") (preload) (userPreload) (getenv(ENV_VAR_HIJACK_LIBS))
 112     (getenv(ENV_VAR_HIJACK_LIBS_M32)) (getenv("LD_PRELOAD"));
 113 }
 114 
 115 // This should be visible to library only.  DmtcpWorker will call
 116 //   this to initialize tmp (ckpt signal) at startup time.  This avoids
 117 //   any later calls to getenv(), at which time the user app may have
 118 //   a wrapper around getenv, modified environ, or other tricks.
 119 //   (Matlab needs this or else it segfaults on restart, and bash plays
 120 //   similar tricks with maintaining its own environment.)
 121 // Used in mtcpinterface.cpp and signalwrappers.cpp.
 122 // FIXME: DO we still want it to be library visible only?
 123 //__attribute__ ((visibility ("hidden")))
 124 int DmtcpWorker::determineCkptSignal()
 125 {
 126   int sig = CKPT_SIGNAL;
 127   char* endp = NULL;
 128   static const char* tmp = getenv(ENV_VAR_SIGCKPT);
 129   if (tmp != NULL) {
 130       sig = strtol(tmp, &endp, 0);
 131       if ((errno != 0) || (tmp == endp))
 132         sig = CKPT_SIGNAL;
 133       if (sig < 1 || sig > 31)
 134         sig = CKPT_SIGNAL;
 135   }
 136   return sig;
 137 }
 138 
 139 /* This function is called at the very beginning of the DmtcpWorker constructor
 140  * to do some initialization work so that DMTCP can later use _real_XXX
 141  * functions reliably. Read the comment at the top of syscallsreal.c for more
 142  * details.
 143  */
 144 static bool dmtcpWrappersInitialized = false;
 145 extern "C" void dmtcp_prepare_wrappers(void)
 146 {
 147   if (!dmtcpWrappersInitialized) {
 148     dmtcp_wrappers_initializing = 1;
 149     initialize_libc_wrappers();
 150     //DmtcpWorker::eventHook(DMTCP_EVENT_INIT_WRAPPERS, NULL);
 151     dmtcp_wrappers_initializing = 0;
 152     initialize_libpthread_wrappers();
 153     dmtcpWrappersInitialized = true;
 154 
 155     /* Register pidVirt_pthread_atfork_child() as the first post-fork handler
 156      * for the child process. This needs to be the first function that is
 157      * called by libc:fork() after the child process is created.
 158      *
 159      * pthread_atfork_child() needs to be the second post-fork handler for the
 160      * child process.
 161      *
 162      * Some dmtcp plugin might also call pthread_atfork and so we call it right
 163      * here before initializing the wrappers.
 164      *
 165      * NOTE: If this doesn't work and someone is able to call pthread_atfork
 166      * before this call, we might want to install a pthread_atfork() wrappers.
 167      */
 168 
 169     /* If we use pthread_atfork here, it fails for Ubuntu 14.04 on ARM.
 170      * To fix it, we use __register_atfork and use the __dso_handle provided by
 171      * the gcc compiler.
 172      */
 173     JASSERT(__register_atfork(NULL, NULL,
 174                            pidVirt_pthread_atfork_child,
 175                            __dso_handle) == 0);
 176 
 177     JASSERT(pthread_atfork(pthread_atfork_prepare,
 178                            pthread_atfork_parent,
 179                            pthread_atfork_child) == 0);
 180   }
 181 }
 182 
 183 static void calculateArgvAndEnvSize()
 184 {
 185   size_t argvSize, envSize;
 186 
 187   vector<string> args = jalib::Filesystem::GetProgramArgs();
 188   argvSize = 0;
 189   for (size_t i = 0; i < args.size(); i++) {
 190     argvSize += args[i].length() + 1;
 191   }
 192   envSize = 0;
 193   if (environ != NULL) {
 194     char *ptr = environ[0];
 195     while (*ptr != '\0' && args[0].compare(ptr) != 0) {
 196       envSize += strlen(ptr) + 1;
 197       ptr += strlen(ptr) + 1;
 198     }
 199   }
 200   envSize += args[0].length();
 201 
 202   ProcessInfo::instance().argvSize(argvSize);
 203   ProcessInfo::instance().envSize(envSize);
 204 }
 205 
 206 static string getLogFilePath()
 207 {
 208 #ifdef DEBUG
 209   ostringstream o;
 210   o << "/proc/self/fd/" << PROTECTED_JASSERTLOG_FD;
 211   return jalib::Filesystem::ResolveSymlink(o.str());
 212 #else
 213   return "";
 214 #endif
 215 }
 216 
 217 static void writeCurrentLogFileNameToPrevLogFile(string& path)
 218 {
 219 #ifdef DEBUG
 220   ostringstream o;
 221   o << "========================================\n"
 222     << "This process exec()'d into a new program\n"
 223     << "Program Name: " << jalib::Filesystem::GetProgramName() << "\n"
 224     << "New JAssertLog Path: " << getLogFilePath() << "\n"
 225     << "========================================\n";
 226 
 227   int fd = open(path.c_str(), O_WRONLY | O_APPEND, 0);
 228   if (fd != -1) {
 229     Util::writeAll(fd, o.str().c_str(), o.str().length());
 230   }
 231   _real_close(fd);
 232 #endif
 233 }
 234 
 235 static void prepareLogAndProcessdDataFromSerialFile()
 236 {
 237 
 238   if (Util::isValidFd(PROTECTED_LIFEBOAT_FD)) {
 239     // This process was under ckpt-control and exec()'d into a new program.
 240     // Find out path of previous log file so that later, we can write the name
 241     // of the new log file into that one.
 242     string prevLogFilePath = getLogFilePath();
 243 
 244     jalib::JBinarySerializeReaderRaw rd ("", PROTECTED_LIFEBOAT_FD);
 245     rd.rewind();
 246     UniquePid::serialize (rd);
 247     Util::initializeLogFile(SharedData::getTmpDir(), "", prevLogFilePath);
 248 
 249     writeCurrentLogFileNameToPrevLogFile(prevLogFilePath);
 250 
 251     DmtcpEventData_t edata;
 252     edata.serializerInfo.fd = PROTECTED_LIFEBOAT_FD;
 253     DmtcpWorker::eventHook(DMTCP_EVENT_POST_EXEC, &edata);
 254     _real_close(PROTECTED_LIFEBOAT_FD);
 255   } else {
 256     // Brand new process (was never under ckpt-control),
 257     // Initialize the log file
 258     Util::initializeLogFile(SharedData::getTmpDir());
 259 
 260     JTRACE("Root of processes tree");
 261     ProcessInfo::instance().setRootOfProcessTree();
 262   }
 263 }
 264 
 265 static void processRlimit()
 266 {
 267 #ifdef __i386__
 268   // Match work begun in dmtcpPrepareForExec()
 269 # if 0
 270   if (getenv("DMTCP_ADDR_COMPAT_LAYOUT")) {
 271     _dmtcp_unsetenv("DMTCP_ADDR_COMPAT_LAYOUT");
 272     // DMTCP had set ADDR_COMPAT_LAYOUT.  Now unset it.
 273     personality((unsigned long)personality(0xffffffff) ^ ADDR_COMPAT_LAYOUT);
 274     JTRACE("unsetting ADDR_COMPAT_LAYOUT");
 275   }
 276 # else
 277   { char * rlim_cur_char = getenv("DMTCP_RLIMIT_STACK");
 278     if (rlim_cur_char != NULL) {
 279       struct rlimit rlim;
 280       getrlimit(RLIMIT_STACK, &rlim);
 281       rlim.rlim_cur = atol(rlim_cur_char);
 282       JTRACE("rlim_cur for RLIMIT_STACK being restored.") (rlim.rlim_cur);
 283       setrlimit(RLIMIT_STACK, &rlim);
 284       _dmtcp_unsetenv("DMTCP_RLIMIT_STACK");
 285     }
 286   }
 287 # endif
 288 #endif
 289 }
 290 
 291 static void segFaultHandler(int sig, siginfo_t* siginfo, void* context)
 292 {
 293   while (1) sleep(1);
 294 }
 295 
 296 static void installSegFaultHandler()
 297 {
 298   // install SIGSEGV handler
 299   struct sigaction act;
 300   memset(&act, 0, sizeof(act));
 301   act.sa_sigaction = segFaultHandler;
 302   act.sa_flags = SA_SIGINFO;
 303   JASSERT (sigaction(SIGSEGV, &act, NULL) == 0) (JASSERT_ERRNO);
 304 }
 305 
 306 //called before user main()
 307 //workerhijack.cpp initializes a static variable theInstance to DmtcpWorker obj
 308 DmtcpWorker::DmtcpWorker()
 309 {
 310   WorkerState::setCurrentState(WorkerState::UNKNOWN);
 311   initializeJalib();
 312   dmtcp_prepare_wrappers();
 313   prepareLogAndProcessdDataFromSerialFile();
 314 
 315   JTRACE("libdmtcp.so:  Running ")
 316     (jalib::Filesystem::GetProgramName()) (getenv ("LD_PRELOAD"));
 317 
 318   processRlimit();
 319 
 320   if (getenv("DMTCP_SEGFAULT_HANDLER") != NULL) {
 321     // Install a segmentation fault handler (for debugging).
 322     installSegFaultHandler();
 323   }
 324 
 325   //This is called for side effect only.  Force this function to call
 326   // getenv(ENV_VAR_SIGCKPT) now and cache it to avoid getenv calls later.
 327   determineCkptSignal();
 328 
 329   // Also cache programName and arguments
 330   string programName = jalib::Filesystem::GetProgramName();
 331   vector<string> args = jalib::Filesystem::GetProgramArgs();
 332 
 333   JASSERT(programName != "dmtcp_coordinator"  &&
 334           programName != "dmtcp_launch"   &&
 335           programName != "dmtcp_nocheckpoint" &&
 336           programName != "dmtcp_comand"       &&
 337           programName != "dmtcp_restart"      &&
 338           programName != "mtcp_restart"       &&
 339           programName != "ssh")
 340     (programName) .Text("This program should not be run under ckpt control");
 341 
 342   calculateArgvAndEnvSize();
 343   restoreUserLDPRELOAD();
 344 
 345   WorkerState::setCurrentState (WorkerState::RUNNING);
 346 
 347   if (ibv_get_device_list && !dmtcp_infiniband_enabled) {
 348     JNOTE("\n\n*** InfiniBand library detected."
 349           "  Please use dmtcp_launch --ib ***\n");
 350   }
 351 
 352   // In libdmtcp.so, notify this event for each plugin.
 353   eventHook(DMTCP_EVENT_INIT, NULL);
 354 
 355   initializeMtcpEngine();
 356   informCoordinatorOfRUNNINGState();
 357 }
 358 
 359 void DmtcpWorker::resetOnFork()
 360 {
 361   eventHook(DMTCP_EVENT_ATFORK_CHILD, NULL);
 362 
 363   cleanupWorker();
 364 
 365   /* If parent process had file connections and it fork()'d a child
 366    * process, the child process would consider the file connections as
 367    * pre-existing and hence wouldn't restore them. This is fixed by making sure
 368    * that when a child process is forked, it shouldn't be looking for
 369    * pre-existing connections because the parent has already done that.
 370    *
 371    * So, here while creating the instance, we do not want to execute everything
 372    * in the constructor since it's not relevant. All we need to call is
 373    * connectToCoordinatorWithHandshake() and initializeMtcpEngine().
 374    */
 375   //new ( &theInstance ) DmtcpWorker ( false );
 376 
 377   ThreadList::resetOnFork();
 378 
 379   DmtcpWorker::_exitInProgress = false;
 380 
 381   WorkerState::setCurrentState ( WorkerState::RUNNING );
 382 
 383 }
 384 
 385 void DmtcpWorker::cleanupWorker()
 386 {
 387   ThreadSync::resetLocks();
 388   WorkerState::setCurrentState(WorkerState::UNKNOWN);
 389   JTRACE("disconnecting from dmtcp coordinator");
 390 }
 391 
 392 void DmtcpWorker::interruptCkpthread()
 393 {
 394   if (ThreadSync::destroyDmtcpWorkerLockTryLock() == EBUSY) {
 395     ThreadList::killCkpthread();
 396     ThreadSync::destroyDmtcpWorkerLockLock();
 397   }
 398 }
 399 
 400 //called after user main()
 401 DmtcpWorker::~DmtcpWorker()
 402 {
 403   /* If the destructor was called, we know that we are exiting
 404    * After setting this, the wrapper execution locks will be ignored.
 405    * FIXME:  A better solution is to add a ZOMBIE state to DmtcpWorker,
 406    *         instead of using a separate variable, _exitInProgress.
 407    */
 408   setExitInProgress();
 409   eventHook(DMTCP_EVENT_EXIT, NULL);
 410   interruptCkpthread();
 411   cleanupWorker();
 412 }
 413 
 414 static void ckptThreadPerformExit()
 415 {
 416   // Ideally, we would like to perform pthread_exit(), but we are in the middle
 417   // of process cleanup (due to the user thread's exit() call) and as a result,
 418   // the static objects are being destroyed.  A call to pthread_exit() also
 419   // results in execution of various cleanup routines.  If the thread tries to
 420   // access any static objects during some cleanup routine, it will cause a
 421   // segfault.
 422   //
 423   // Our approach to loop here while we wait for the process to terminate.
 424   // This guarantees that we never access any static objects from this point
 425   // forward.
 426   while (1) sleep(1);
 427 }
 428 
 429 void DmtcpWorker::waitForCoordinatorMsg(string msgStr,
 430                                                DmtcpMessageType type)
 431 {
 432   if (dmtcp_no_coordinator()) {
 433     if (type == DMT_DO_SUSPEND) {
 434       string shmFile = jalib::Filesystem::GetDeviceName(PROTECTED_SHM_FD);
 435       JASSERT(!shmFile.empty());
 436       unlink(shmFile.c_str());
 437       CoordinatorAPI::instance().waitForCheckpointCommand();
 438       ProcessInfo::instance().numPeers(1);
 439       ProcessInfo::instance().compGroup(SharedData::getCompId());
 440     }
 441     return;
 442   }
 443 
 444   if (type == DMT_DO_SUSPEND) {
 445     if (ThreadSync::destroyDmtcpWorkerLockTryLock() != 0) {
 446       JTRACE("User thread is performing exit()."
 447                " ckpt thread exit()ing as well");
 448       ckptThreadPerformExit();
 449     }
 450     if (exitInProgress()) {
 451       ThreadSync::destroyDmtcpWorkerLockUnlock();
 452       ckptThreadPerformExit();
 453     }
 454   }
 455 
 456   DmtcpMessage msg;
 457 
 458   if (type == DMT_DO_SUSPEND) {
 459     // Make a dummy syscall to inform superior of our status before we go into
 460     // select. If ptrace is disabled, this call has no significant effect.
 461     _real_syscall(DMTCP_FAKE_SYSCALL);
 462   } else {
 463     msg.type = DMT_OK;
 464     msg.state = WorkerState::currentState();
 465     CoordinatorAPI::instance().sendMsgToCoordinator(msg);
 466   }
 467 
 468   JTRACE("waiting for " + msgStr + " message");
 469   CoordinatorAPI::instance().recvMsgFromCoordinator(&msg);
 470   if (type == DMT_DO_SUSPEND && exitInProgress()) {
 471     ThreadSync::destroyDmtcpWorkerLockUnlock();
 472     ckptThreadPerformExit();
 473   }
 474 
 475   msg.assertValid();
 476   if (msg.type == DMT_KILL_PEER) {
 477     JTRACE("Received KILL message from coordinator, exiting");
 478     _exit (0);
 479   }
 480 
 481   JASSERT(msg.type == type) (msg.type) (type);
 482 
 483   // Coordinator sends some computation information along with the SUSPEND
 484   // message. Extracting that.
 485   if (type == DMT_DO_SUSPEND) {
 486     SharedData::updateGeneration(msg.compGroup.computationGeneration());
 487     JASSERT(SharedData::getCompId() == msg.compGroup.upid())
 488       (SharedData::getCompId()) (msg.compGroup);
 489   } else if (type == DMT_DO_FD_LEADER_ELECTION) {
 490     JTRACE("Computation information") (msg.compGroup) (msg.numPeers);
 491     ProcessInfo::instance().compGroup(msg.compGroup);
 492     ProcessInfo::instance().numPeers(msg.numPeers);
 493   }
 494 }
 495 
 496 void DmtcpWorker::informCoordinatorOfRUNNINGState()
 497 {
 498   DmtcpMessage msg;
 499 
 500   JASSERT(WorkerState::currentState() == WorkerState::RUNNING);
 501 
 502   msg.type = DMT_OK;
 503   msg.state = WorkerState::currentState();
 504   CoordinatorAPI::instance().sendMsgToCoordinator(msg);
 505 }
 506 
 507 void DmtcpWorker::waitForStage1Suspend()
 508 {
 509   JTRACE("running");
 510 
 511   WorkerState::setCurrentState (WorkerState::RUNNING);
 512 
 513   waitForCoordinatorMsg ("SUSPEND", DMT_DO_SUSPEND);
 514 
 515   JTRACE("got SUSPEND message, preparing to acquire all ThreadSync locks");
 516   ThreadSync::acquireLocks();
 517 
 518   JTRACE("Starting checkpoint, suspending...");
 519 }
 520 
 521 void DmtcpWorker::waitForStage2Checkpoint()
 522 {
 523   WorkerState::setCurrentState (WorkerState::SUSPENDED);
 524   JTRACE("suspended");
 525 
 526   if (exitInProgress()) {
 527     ThreadSync::destroyDmtcpWorkerLockUnlock();
 528     ckptThreadPerformExit();
 529   }
 530   ThreadSync::destroyDmtcpWorkerLockUnlock();
 531 
 532   ThreadSync::releaseLocks();
 533 
 534   eventHook(DMTCP_EVENT_THREADS_SUSPEND, NULL);
 535 
 536   waitForCoordinatorMsg ("FD_LEADER_ELECTION", DMT_DO_FD_LEADER_ELECTION);
 537 
 538   eventHook(DMTCP_EVENT_LEADER_ELECTION, NULL);
 539 
 540   WorkerState::setCurrentState (WorkerState::FD_LEADER_ELECTION);
 541 
 542   waitForCoordinatorMsg ("DRAIN", DMT_DO_DRAIN);
 543 
 544   WorkerState::setCurrentState (WorkerState::DRAINED);
 545 
 546   eventHook(DMTCP_EVENT_DRAIN, NULL);
 547 
 548   waitForCoordinatorMsg ("CHECKPOINT", DMT_DO_CHECKPOINT);
 549   JTRACE("got checkpoint message");
 550 
 551   eventHook(DMTCP_EVENT_WRITE_CKPT, NULL);
 552 
 553   // Unmap shared area
 554   SharedData::preCkpt();
 555 }
 556 
 557 void DmtcpWorker::waitForStage3Refill(bool isRestart)
 558 {
 559   DmtcpEventData_t edata;
 560   JTRACE("checkpointed");
 561 
 562   WorkerState::setCurrentState (WorkerState::CHECKPOINTED);
 563 
 564 #ifdef COORD_NAMESERVICE
 565   waitForCoordinatorMsg("REGISTER_NAME_SERVICE_DATA",
 566                           DMT_DO_REGISTER_NAME_SERVICE_DATA);
 567   edata.nameserviceInfo.isRestart = isRestart;
 568   eventHook(DMTCP_EVENT_REGISTER_NAME_SERVICE_DATA, &edata);
 569   JTRACE("Key Value Pairs registered with the coordinator");
 570   WorkerState::setCurrentState(WorkerState::NAME_SERVICE_DATA_REGISTERED);
 571 
 572   waitForCoordinatorMsg("SEND_QUERIES", DMT_DO_SEND_QUERIES);
 573   eventHook(DMTCP_EVENT_SEND_QUERIES, &edata);
 574   JTRACE("Queries sent to the coordinator");
 575   WorkerState::setCurrentState(WorkerState::DONE_QUERYING);
 576 #endif
 577 
 578   waitForCoordinatorMsg ("REFILL", DMT_DO_REFILL);
 579 
 580   edata.refillInfo.isRestart = isRestart;
 581   DmtcpWorker::eventHook(DMTCP_EVENT_REFILL, &edata);
 582 }
 583 
 584 void DmtcpWorker::waitForStage4Resume(bool isRestart)
 585 {
 586   JTRACE("refilled");
 587   WorkerState::setCurrentState (WorkerState::REFILLED);
 588   waitForCoordinatorMsg ("RESUME", DMT_DO_RESUME);
 589   JTRACE("got resume message");
 590   DmtcpEventData_t edata;
 591   edata.resumeInfo.isRestart = isRestart;
 592   DmtcpWorker::eventHook(DMTCP_EVENT_THREADS_RESUME, &edata);
 593 }
 594 
 595 void dmtcp_CoordinatorAPI_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 596 void dmtcp_SharedData_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 597 void dmtcp_ProcessInfo_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 598 void dmtcp_UniquePid_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 599 void dmtcp_ProcName_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 600 void dmtcp_Terminal_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 601 void dmtcp_Syslog_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 602 void dmtcp_Alarm_EventHook(DmtcpEvent_t event, DmtcpEventData_t *data);
 603 
 604 void DmtcpWorker::eventHook(DmtcpEvent_t event, DmtcpEventData_t *data)
 605 {
 606   static jalib::JBuffer buf(0); // To force linkage of jbuffer.cpp
 607   dmtcp_Syslog_EventHook(event, data);
 608   dmtcp_Terminal_EventHook(event, data);
 609   dmtcp_ProcName_EventHook(event, data);
 610   dmtcp_UniquePid_EventHook(event, data);
 611   dmtcp_CoordinatorAPI_EventHook(event, data);
 612   dmtcp_SharedData_EventHook(event, data);
 613   dmtcp_ProcessInfo_EventHook(event, data);
 614   dmtcp_Alarm_EventHook(event, data);
 615   if (dmtcp_event_hook != NULL) {
 616     dmtcp_event_hook(event, data);
 617   }
 618 }

/* [<][>][^][v][top][bottom][index][help] */