root/plugin/dl/dlwrappers.cpp

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

DEFINITIONS

This source file includes following definitions.
  1. dlopen
  2. dlclose

   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 the dmtcp/src module of DMTCP (DMTCP:dmtcp/src).  *
   6  *                                                                          *
   7  *  DMTCP:dmtcp/src 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:dmtcp/src 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 <unistd.h>
  24 #include "dmtcp.h"
  25 
  26 #define _real_dlopen  NEXT_FNC(dlopen)
  27 #define _real_dlclose NEXT_FNC(dlclose)
  28 
  29 extern "C" int dmtcp_libdlLockLock();
  30 extern "C" void dmtcp_libdlLockUnlock();
  31 
  32 /* Reason for using thread_performing_dlopen_dlsym:
  33  *
  34  * dlsym/dlopen/dlclose make a call to calloc() internally. We do not want to
  35  * checkpoint while we are in the midst of dlopen etc. as it can lead to
  36  * undesired behavior. To do so, we use WRAPPER_EXECUTION_DISABLE_CKPT() at the
  37  * beginning of the funtion. However, if a checkpoint request is received right
  38  * after WRAPPER_EXECUTION_DISABLE_CKPT(), the ckpt-thread is queued for wrlock
  39  * on the pthread-rwlock and any subsequent request for rdlock by other threads
  40  * will have to wait until the ckpt-thread releases the lock. However, in this
  41  * scenario, dlopen calls calloc, which then calls
  42  * WRAPPER_EXECUTION_DISABLE_CKPT() and hence resulting in a deadlock.
  43  *
  44  * We set this variable to true, once we are inside the dlopen/dlsym/dlerror
  45  * wrapper, so that the calling thread won't try to acquire the lock later on.
  46  *
  47  * EDIT: Instead of acquiring wrapperExecutionLock, we acquire libdlLock.
  48  * libdlLock is a higher priority lock than wrapperExectionLock i.e. during
  49  * checkpointing this lock is acquired before wrapperExecutionLock by the
  50  * ckpt-thread.
  51  * Rationale behind not using wrapperExecutionLock and creating an extra lock:
  52  *   When loading a shared library, dlopen will initialize the static objects
  53  *   in the shared library by calling their corresponding constructors.
  54  *   Further, the constructor might call fork/exec to create new
  55  *   process/program. Finally, fork/exec require the wrapperExecutionLock in
  56  *   exclusive mode (writer lock). However, if dlopen wrapper acquires the
  57  *   wrapperExecutionLock, the fork wrapper will deadlock when trying to get
  58  *   writer lock.
  59  *
  60  * EDIT: The dlopen() wrappers causes the problems with the semantics of RPATH
  61  * associated with the caller library. In future, we can work without this
  62  * plugin by detecting if we are in the middle of a dlopen by looking up the
  63  * stack frames.
  64  */
  65 
  66 extern "C"
  67 void *dlopen(const char *filename, int flag)
  68 {
  69   bool lockAcquired = dmtcp_libdlLockLock();
  70   void *ret = _real_dlopen(filename, flag);
  71   if (lockAcquired) {
  72     dmtcp_libdlLockUnlock();
  73   }
  74   return ret;
  75 }
  76 
  77 extern "C"
  78 int dlclose(void *handle)
  79 {
  80   bool lockAcquired = dmtcp_libdlLockLock();
  81   int ret = _real_dlclose(handle);
  82   if (lockAcquired) {
  83     dmtcp_libdlLockUnlock();
  84   }
  85   return ret;
  86 }
  87 

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