inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
{
   #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
   //Posix does not support infinity absolute time so handle it here
   if(abs_time == boost::posix_time::pos_infin){
      semaphore_wait(handle);
      return true;
   }

   timespec tspec = ptime_to_timespec(abs_time);
   for (;;){
      int res = sem_timedwait(handle, &tspec);
      if(res == 0)
         return true;
      if (res > 0){
         //buggy glibc, copy the returned error code to errno
         errno = res;
      }
      if(system_error_code() == ETIMEDOUT){
         return false;
      }
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }
   return false;
   #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS

   semaphore_wrapper_try_wrapper swtw(handle);
   ipcdetail::lock_to_wait<semaphore_wrapper_try_wrapper> lw(swtw);
   return ipcdetail::try_based_timed_lock(lw, abs_time);

   #endif   //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
}
inline void create_tmp_and_clean_old(std::string &tmp_name)
{
   //First get the temp directory
   std::string root_tmp_name;
   get_tmp_base_dir(root_tmp_name);

   //If fails, check that it's because already exists
   if(!create_directory(root_tmp_name.c_str())){
      error_info info(system_error_code());
      if(info.get_error_code() != already_exists_error){
         throw interprocess_exception(info);
      }
   }

   #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
      tmp_folder(tmp_name);

      //If fails, check that it's because already exists
      if(!create_directory(tmp_name.c_str())){
         error_info info(system_error_code());
         if(info.get_error_code() != already_exists_error){
            throw interprocess_exception(info);
         }
      }
      //Now erase all old directories created in the previous boot sessions
      std::string subdir = tmp_name;
      subdir.erase(0, root_tmp_name.size()+1);
      delete_subdirectories(root_tmp_name, subdir.c_str());
   #else
      tmp_name = root_tmp_name;
   #endif
}
Exemple #3
0
inline bool semaphore_timed_wait(sem_t *handle, const boost::posix_time::ptime &abs_time)
{
   #ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
   timespec tspec = detail::ptime_to_timespec(abs_time);
   for (;;){
      int res = sem_timedwait(handle, &tspec);
      if(res == 0)
         return true;
      if (res > 0){
         //buggy glibc, copy the returned error code to errno
         errno = res;
      }
      if(system_error_code() == ETIMEDOUT){
         return false;
      }
      throw interprocess_exception(system_error_code());
   }
   return false;
   #else //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
   boost::posix_time::ptime now;
   while((now = microsec_clock::universal_time()) < abs_time){
      if(semaphore_try_wait(handle))
         return true;
      thread_yield();
   }
   return false;
   #endif   //#ifdef BOOST_INTERPROCESS_POSIX_TIMEOUTS
}
Exemple #4
0
inline bool semaphore_try_wait(sem_t *handle)
{
   int res = sem_trywait(handle);
   if(res == 0)
      return true;
   if(system_error_code() == EAGAIN){
      return false;
   }
   throw interprocess_exception(system_error_code());
   return false;
}
 void lock()
 {
    if(winapi::wait_for_single_object(m_mtx_hnd, winapi::infinite_time) != winapi::wait_object_0){
       error_info err = system_error_code();
       throw interprocess_exception(err);
    }
 }
Exemple #6
0
inline void semaphore_wait(sem_t *handle)
{
   int ret = sem_wait(handle);
   if(ret != 0){
      throw interprocess_exception(system_error_code());
   }
}
Exemple #7
0
inline void file_wrapper::truncate(offset_t length)
{
   if(!truncate_file(m_handle, length)){
      error_info err(system_error_code());
      throw interprocess_exception(err);
   }
}
inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const boost::posix_time::ptime &abs_time)
{
   const boost::posix_time::ptime cur_time = microsec_clock::universal_time();
   //Windows uses relative wait times so check for negative waits
   //and implement as 0 wait to allow try-semantics as POSIX mandates.
   unsigned long time = 0u;
   if (abs_time == boost::posix_time::pos_infin){
      time = winapi::infinite_time;
   }
   else if(abs_time > cur_time){
      time = (abs_time - cur_time).total_milliseconds();
   }

   unsigned long ret = winapi::wait_for_single_object(handle, time);
   if(ret == winapi::wait_object_0){
      return true;
   }
   else if(ret == winapi::wait_timeout){
      return false;
   }
   else if(ret == winapi::wait_abandoned){ //Special case for orphaned mutexes
      winapi::release_mutex(handle);
      throw interprocess_exception(owner_dead_error);
   }
   else{
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }
}
inline bool winapi_wrapper_timed_wait_for_single_object(void *handle, const geofeatures_boost::posix_time::ptime &abs_time)
{
   //Windows does not support infinity abs_time so check it
   if(abs_time == geofeatures_boost::posix_time::pos_infin){
      winapi_wrapper_wait_for_single_object(handle);
      return true;
   }
   const geofeatures_boost::posix_time::ptime cur_time = microsec_clock::universal_time();
   //Windows uses relative wait times so check for negative waits
   //and implement as 0 wait to allow try-semantics as POSIX mandates.
   unsigned long ret = winapi::wait_for_single_object
      ( handle
      , (abs_time <= cur_time) ? 0u
                                 : (abs_time - cur_time).total_milliseconds()
      );
   if(ret == winapi::wait_object_0){
      return true;
   }
   else if(ret == winapi::wait_timeout){
      return false;
   }
   else{
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }
}
Exemple #10
0
inline void semaphore_post(sem_t *handle)
{
   int ret = sem_post(handle);
   if(ret != 0){
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }
}
Exemple #11
0
inline void semaphore_init(sem_t *handle, int initialCount)
{
   int ret = sem_init(handle, 1, initialCount);
   //According to SUSV3 version 2003 edition, the return value of a successful
   //sem_init call is not defined, but -1 is returned on failure.
   //In the future, a successful call might be required to return 0.
   if(ret == -1){
      throw interprocess_exception(system_error_code());
   }
}
inline bool semaphore_try_wait(sem_t *handle)
{
   while (1) {
      int res = sem_trywait(handle);
      if (res == 0)
         return true;
      if (system_error_code() != EINTR)
         return false;
   }
}
inline void semaphore_wait(sem_t *handle)
{
   while (1) {
      int res = sem_wait(handle);
      if (res == 0)
         return;
      if (system_error_code() != EINTR)
         return;
   }
}
Exemple #14
0
inline bool open_or_create_directory(const char *dir_name)
{
   //If fails, check that it's because it already exists
   if(!create_directory(dir_name)){
      error_info info(system_error_code());
      if(info.get_error_code() != already_exists_error){
         return false;
      }
   }
   return true;
}
inline void tmp_filename(const char *filename, std::string &tmp_name)
{
   const char *tmp_dir = get_temporary_path();
   if(!tmp_dir){
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }
   tmp_name = tmp_dir;

   //Remove final null.
   tmp_name += "/boost_interprocess/";
   tmp_name += filename;
}
 bool try_lock()
 {
    unsigned long ret = winapi::wait_for_single_object(m_mtx_hnd, 0);
    if(ret == winapi::wait_object_0){
       return true;
    }
    else if(ret == winapi::wait_timeout){
       return false;
    }
    else{
       error_info err = system_error_code();
       throw interprocess_exception(err);
    }
 }
inline bool winapi_wrapper_try_wait_for_single_object(void *handle)
{
   unsigned long ret = winapi::wait_for_single_object(handle, 0);
   if(ret == winapi::wait_object_0){
      return true;
   }
   else if(ret == winapi::wait_timeout){
      return false;
   }
   else{
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }
}
inline void winapi_wrapper_wait_for_single_object(void *handle)
{
   unsigned long ret = winapi::wait_for_single_object(handle, winapi::infinite_time);
   if(ret != winapi::wait_object_0){
      if(ret != winapi::wait_abandoned){
         error_info err = system_error_code();
         throw interprocess_exception(err);
      }
      else{ //Special case for orphaned mutexes
         winapi::release_mutex(handle);
         throw interprocess_exception(owner_dead_error);
      }
   }
}
Exemple #19
0
   robust_mutex_lock_file()
   {
      permissions p;
      p.set_unrestricted();
      //Remove old lock files of other processes
      remove_old_robust_lock_files();
      //Create path and obtain lock file path for this process
      create_and_get_robust_lock_file_path(fname, get_current_process_id());

      //Now try to open or create the lock file
      fd = create_or_open_file(fname.c_str(), read_write, p);
      //If we can't open or create it, then something unrecoverable has happened
      if(fd == invalid_file()){
         throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: could not open or create file");
      }

      //Now we must take in care a race condition with another process
      //calling "remove_old_robust_lock_files()". No other threads from this
      //process will be creating the lock file because intermodule_singleton
      //guarantees this. So let's loop acquiring the lock and checking if we
      //can't exclusively create the file (if the file is erased by another process
      //then this exclusive open would fail). If the file can't be exclusively created
      //then we have correctly open/create and lock the file. If the file can
      //be exclusively created, then close previous locked file and try again.
      while(1){
         bool acquired;
         if(!try_acquire_file_lock(fd, acquired) || !acquired ){
            throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: try_acquire_file_lock");
         }
         //Creating exclusively must fail with already_exists_error
         //to make sure we've locked the file and no one has
         //deleted it between creation and locking
         file_handle_t fd2 = create_new_file(fname.c_str(), read_write, p);
         if(fd2 != invalid_file()){
            close_file(fd);
            fd = fd2;
            continue;
         }
         //If exclusive creation fails with expected error go ahead
         else if(error_info(system_error_code()).get_error_code() == already_exists_error){ //must already exist
            //Leak descriptor to mantain the file locked until the process dies
            break;
         }
         //If exclusive creation fails with unexpected error throw an unrecoverable error
         else{
            close_file(fd);
            throw interprocess_exception(other_error, "Robust emulation robust_mutex_lock_file constructor failed: create_file filed with unexpected error");
         }
      }
   }
inline void create_tmp_dir_and_get_filename(const char *filename, std::string &tmp_name)
{
   //First get the temp directory
   get_tmp_base_dir(tmp_name);

   //If fails, check that it's because already exists
   if(!create_directory(tmp_name.c_str())){
      error_info info(system_error_code());
      if(info.get_error_code() != already_exists_error){
         throw interprocess_exception(info);
      }
   }

   #ifdef BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME
   //Create a new subdirectory with the bootstamp
   std::string root_tmp_name = tmp_name;
   tmp_name += '/';
   //Obtain bootstamp string
   std::string bootstamp;
   get_bootstamp(bootstamp);
   tmp_name += bootstamp; 

   //If fails, check that it's because already exists
   if(!create_directory(tmp_name.c_str())){
      error_info info(system_error_code());
      if(info.get_error_code() != already_exists_error){
         throw interprocess_exception(info);
      }
   }
   //Now erase all old directories created in the previous boot sessions
   delete_subdirectories(root_tmp_name, bootstamp.c_str());
   #endif

   //Add filename
   tmp_name += '/';
   tmp_name += filename;
}
inline void create_shared_dir_and_clean_old(std::string &shared_dir)
{
   #if defined(BOOST_INTERPROCESS_SHARED_DIR_PATH) || defined(BOOST_INTERPROCESS_SHARED_DIR_FUNC)
      get_shared_dir(shared_dir);
   #else
      //First get the temp directory
      std::string root_shared_dir;
      get_shared_dir_root(root_shared_dir);

      //If fails, check that it's because already exists
      if(!create_directory(root_shared_dir.c_str())){
         error_info info(system_error_code());
         if(info.get_error_code() != already_exists_error){
            throw interprocess_exception(info);
         }
      }

      #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME)
         get_shared_dir(shared_dir);

         //If fails, check that it's because already exists
         if(!create_directory(shared_dir.c_str())){
            error_info info(system_error_code());
            if(info.get_error_code() != already_exists_error){
               throw interprocess_exception(info);
            }
         }
         //Now erase all old directories created in the previous boot sessions
         std::string subdir = shared_dir;
         subdir.erase(0, root_shared_dir.size()+1);
         delete_subdirectories(root_shared_dir, subdir.c_str());
      #else
         shared_dir = root_shared_dir;
      #endif
   #endif
}
inline void create_tmp_dir_and_get_filename(const char *filename, std::string &tmp_name)
{
   const char *tmp_path = get_temporary_path(); 
   if(!tmp_path){
      error_info err = system_error_code();
      throw interprocess_exception(err);
   }

   tmp_name = tmp_path;
   tmp_name += "/boost_interprocess";

   //Create the temporary directory.
   //If fails, check that it's because already exists
   if(!create_directory(tmp_name.c_str())){
      error_info info(system_error_code());
      if(info.get_error_code() != already_exists_error){
         throw interprocess_exception(info);
      }
   }

   //Add filename
   tmp_name += '/';
   tmp_name += filename;
}
Exemple #23
0
 //!Creates a new XSI  shared memory with a key obtained from a call to ftok (with path
 //!"path" and id "id"), of size "size" and permissions "perm".
 //!If the shared memory previously exists, throws an error.
 xsi_key(const char *path, boost::uint8_t id)
 {
    key_t key;   
    if(path){
       key  = ::ftok(path, id);
       if(((key_t)-1) == key){
          error_info err = system_error_code();
          throw interprocess_exception(err);
       }
    }
    else{
       key = IPC_PRIVATE;
    }
    m_key = key;
 }
   bool timed_lock(const boost::posix_time::ptime &abs_time)
   {
      if(abs_time == boost::posix_time::pos_infin){
         this->lock();
         return true;
      }

      unsigned long ret = winapi::wait_for_single_object
         (m_mtx_hnd, (abs_time - microsec_clock::universal_time()).total_milliseconds());
      if(ret == winapi::wait_object_0){
         return true;
      }
      else if(ret == winapi::wait_timeout){
         return false;
      }
      else{
         error_info err = system_error_code();
         throw interprocess_exception(err);
      }
   }
Exemple #25
0
inline bool file_wrapper::priv_open_or_create
   (detail::create_enum_t type, 
    const char *filename,
    mode_t mode)
{
   m_filename = filename;

   if(mode != read_only && mode != read_write){
      error_info err(mode_error);
      throw interprocess_exception(err);
   }

   //Open file existing native API to obtain the handle
   switch(type){
      case detail::DoOpen:
         m_handle = open_existing_file(filename, mode);
      break;
      case detail::DoCreate:
         m_handle = create_new_file(filename, mode);
      break;
      case detail::DoOpenOrCreate:
         m_handle = create_or_open_file(filename, mode);
      break;
      default:
         {
            error_info err = other_error;
            throw interprocess_exception(err);
         }
   }

   //Check for error
   if(m_handle == invalid_file()){
      throw interprocess_exception(error_info(system_error_code()));
   }

   m_mode = mode;
   return true;
}
Exemple #26
0
inline bool robust_spin_mutex<Mutex>::is_owner_dead(boost::uint32_t own)
{
   //If owner is an invalid id, then it's clear it's dead
   if(own == (boost::uint32_t)get_invalid_process_id()){
      return true;
   }

   //Obtain the lock filename of the owner field
   std::string file;
   this->owner_to_filename(own, file);

   //Now the logic is to open and lock it
   file_handle_t fhnd = open_existing_file(file.c_str(), read_write);

   if(fhnd != invalid_file()){
      //If we can open the file, lock it.
      bool acquired;
      if(try_acquire_file_lock(fhnd, acquired) && acquired){
         //If locked, just delete the file
         delete_file(file.c_str());
         close_file(fhnd);
         return true;
      }
      //If not locked, the owner is suppossed to be still alive
      close_file(fhnd);
   }
   else{
      //If the lock file does not exist then the owner is dead (a previous cleanup)
      //function has deleted the file. If there is another reason, then this is
      //an unrecoverable error
      if(error_info(system_error_code()).get_error_code() == not_found_error){
         return true;
      }
   }
   return false;
}
Exemple #27
0
inline void windows_named_sync::open_or_create
   ( create_enum_t creation_type
   , const char *name
   , const permissions &perm
   , windows_named_sync_interface &sync_interface)
{
   std::string aux_str(name);
   m_file_hnd  = winapi::invalid_handle_value;
   //Use a file to emulate POSIX lifetime semantics. After this logic
   //we'll obtain the ID of the native handle to open in aux_str
   {
      create_shared_dir_cleaning_old_and_get_filepath(name, aux_str);
      //Create a file with required permissions.
      m_file_hnd = winapi::create_file
         ( aux_str.c_str()
         , winapi::generic_read | winapi::generic_write
         , creation_type == DoOpen ? winapi::open_existing :
               (creation_type == DoCreate ? winapi::create_new : winapi::open_always)
         , 0
         , (winapi::interprocess_security_attributes*)perm.get_permissions());

      //Obtain OS error in case something has failed
      error_info err;
      bool success = false;
      if(m_file_hnd != winapi::invalid_handle_value){
         //Now lock the file
         const std::size_t buflen = sync_interface.get_data_size();
         typedef __int64 unique_id_type;
         const std::size_t sizeof_file_info = sizeof(unique_id_type) + buflen;
         winapi::interprocess_overlapped overlapped;
         if(winapi::lock_file_ex
            (m_file_hnd, winapi::lockfile_exclusive_lock, 0, sizeof_file_info, 0, &overlapped)){
            __int64 filesize = 0;
            //Obtain the unique id to open the native semaphore.
            //If file size was created
            if(winapi::get_file_size(m_file_hnd, filesize)){
               unsigned long written_or_read = 0;
               unique_id_type unique_id_val;
               if(static_cast<std::size_t>(filesize) != sizeof_file_info){
                  winapi::set_end_of_file(m_file_hnd);
                  winapi::query_performance_counter(&unique_id_val);
                  const void *buf = sync_interface.buffer_with_init_data_to_file();
                  //Write unique ID in file. This ID will be used to calculate the semaphore name
                  if(winapi::write_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0)  &&
                     written_or_read == sizeof(unique_id_val) &&
                     winapi::write_file(m_file_hnd, buf, buflen, &written_or_read, 0) &&
                     written_or_read == buflen ){
                     success = true;
                  }
                  winapi::get_file_size(m_file_hnd, filesize);
                  BOOST_ASSERT(std::size_t(filesize) == sizeof_file_info);
               }
               else{
                  void *buf = sync_interface.buffer_to_store_init_data_from_file();
                  if(winapi::read_file(m_file_hnd, &unique_id_val, sizeof(unique_id_val), &written_or_read, 0)  &&
                     written_or_read == sizeof(unique_id_val) &&
                     winapi::read_file(m_file_hnd, buf, buflen, &written_or_read, 0)  &&
                     written_or_read == buflen   ){
                     success = true;
                  }
               }
               if(success){
                  //Now create a global semaphore name based on the unique id
                  char unique_id_name[sizeof(unique_id_val)*2+1];
                  std::size_t name_suffix_length = sizeof(unique_id_name);
                  bytes_to_str(&unique_id_val, sizeof(unique_id_val), &unique_id_name[0], name_suffix_length);
                  success = sync_interface.open(creation_type, unique_id_name);
               }
            }

            //Obtain OS error in case something has failed
            err = system_error_code();

            //If this fails we have no possible rollback so don't check the return
            if(!winapi::unlock_file_ex(m_file_hnd, 0, sizeof_file_info, 0, &overlapped)){
               err = system_error_code();
            }
         }
         else{
            //Obtain OS error in case something has failed
            err = system_error_code();
         }
      }
      else{
         err = system_error_code();
      }

      if(!success){
         if(m_file_hnd != winapi::invalid_handle_value){
            winapi::close_handle(m_file_hnd);
            m_file_hnd = winapi::invalid_handle_value;
         }
         //Throw as something went wrong
         throw interprocess_exception(err);
      }
   }
}