interprocess file_lock timed_lock not returning false after timeout
Hi all! I think there are two issues, one is a documentation issue, the other might be a bug with boost::interprocess file_lock. The documentation issue is that it was not clear to me by reading the documentation on file_lock that it is a RAII-style class. By reading that it has process lifetime, I assumed that once acquired, the lock would be held even after the file_lock object is destroyed. Once I figured this out, I changed the file_lock to a static method variable and ran into the following issue. I have two processes that use the following class method that I wrote. They both try to acquire a lock on the same file and the lock must be held until the process exits. When I start the first process, it acquires the lock correctly. When I start up the second process, I would expect the following code to return false after 10 seconds //// static boost::interprocess::file_lock process_flock(processLockFile.string().c_str()); if (!process_flock.timed_lock(wait_until)){ //// However, when I read through the logs, I see that the process reaches the timed_lock call and gets stuck there. Can you please help me diagnose this? I'm attaching the entire method with log lines treated for brevity. Boost version is 1.53, running on Centos 6. Thanks! ------------------------8<-------------- ReturnStatus ProcessLocker::lockViaFile() { L_CONTEXT("ProcessLocker::lockViaFile()"); path lockDirectory(lockFileDirectoryName); if (!exists(lockDirectory)){ L_ERROR("missing lock directory"); return r_error; } if (!is_directory(lockDirectory)){ L_ERROR("lock path is not a directory"); return r_error; } path globalLockFile = lockDirectory / "general-locking.lock"; // make sure file exists boost::filesystem::ofstream globalfile(globalLockFile, std::ios::out); // we do nothing with it... globalfile.close(); std::string filename; // class member, this is the process identifier, and is the same between invocations filename.append(identifier); filename.append(".lock"); path processLockFile = lockDirectory / filename; // make sure file exists boost::filesystem::ofstream processfile(processLockFile, std::ios::out); // we do nothing with it... processfile.close(); try { ptime now(second_clock::local_time()); ptime wait_until = now +seconds(10); L_DEBUG("Waiting for global lock until " << wait_until); boost::interprocess::file_lock global_flock(globalLockFile.string().c_str()); if (!global_flock.timed_lock(wait_until)){ L_ERROR("Cannot create global lock"); return r_error; } try { L_DEBUG("Waiting for process lock until " << wait_until); static boost::interprocess::file_lock process_flock(processLockFile.string().c_str()); if (!process_flock.timed_lock(wait_until)){ global_flock.unlock(); // this point is never reached!? L_ERROR("Cannot create process lock"); return r_error; } global_flock.unlock(); L_DEBUG("Obtained process lock, freeing global lock"); return r_ok; } catch (std::exception& e){ global_flock.unlock(); L_ERROR("Cannot create process lock, freeing global lock"); return r_error; } } catch (std::exception& e){ L_ERROR("Cannot create global lock"); return r_error; } } -- Claudio Bantaloukas
Found the culprit, should have used second_clock::universal_time instead of
second_clock::local_time
On Mon, Jul 29, 2013 at 10:37 PM, Claudio Bantaloukas wrote: Hi all!
I think there are two issues, one is a documentation issue, the other
might be a bug with boost::interprocess file_lock. The documentation issue is that it was not clear to me by reading the
documentation on file_lock that it is a RAII-style class. By reading that
it has process lifetime, I assumed that once acquired, the lock would be
held even after the file_lock object is destroyed. Once I figured this out, I changed the file_lock to a static method
variable and ran into the following issue. I have two processes that use the following class method that I wrote.
They both try to acquire a lock on the same file and the lock must be held
until the process exits. When I start the first process, it acquires the lock correctly.
When I start up the second process, I would expect the following code to
return false after 10 seconds
////
static boost::interprocess::file_lock
process_flock(processLockFile.string().c_str());
if (!process_flock.timed_lock(wait_until)){
//// However, when I read through the logs, I see that the process reaches the
timed_lock call and gets stuck there. Can you please help me diagnose this? I'm attaching the entire method with log lines treated for brevity.
Boost version is 1.53, running on Centos 6. Thanks!
------------------------8<--------------
ReturnStatus ProcessLocker::lockViaFile()
{
L_CONTEXT("ProcessLocker::lockViaFile()");
path lockDirectory(lockFileDirectoryName);
if (!exists(lockDirectory)){
L_ERROR("missing lock directory");
return r_error;
}
if (!is_directory(lockDirectory)){
L_ERROR("lock path is not a directory");
return r_error;
} path globalLockFile = lockDirectory / "general-locking.lock"; // make sure file exists
boost::filesystem::ofstream globalfile(globalLockFile, std::ios::out);
// we do nothing with it...
globalfile.close(); std::string filename;
// class member, this is the process identifier, and is the same between
invocations
filename.append(identifier); filename.append(".lock"); path processLockFile = lockDirectory / filename;
// make sure file exists
boost::filesystem::ofstream processfile(processLockFile, std::ios::out);
// we do nothing with it...
processfile.close(); try {
ptime now(second_clock::local_time());
ptime wait_until = now +seconds(10);
L_DEBUG("Waiting for global lock until " << wait_until);
boost::interprocess::file_lock
global_flock(globalLockFile.string().c_str());
if (!global_flock.timed_lock(wait_until)){
L_ERROR("Cannot create global lock");
return r_error;
} try {
L_DEBUG("Waiting for process lock until " << wait_until);
static boost::interprocess::file_lock
process_flock(processLockFile.string().c_str());
if (!process_flock.timed_lock(wait_until)){
global_flock.unlock();
// this point is never reached!?
L_ERROR("Cannot create process lock");
return r_error;
}
global_flock.unlock();
L_DEBUG("Obtained process lock, freeing global lock");
return r_ok;
} catch (std::exception& e){
global_flock.unlock();
L_ERROR("Cannot create process lock, freeing global lock");
return r_error;
} } catch (std::exception& e){
L_ERROR("Cannot create global lock");
return r_error;
}
} --
Claudio Bantaloukas --
Claudio Bantaloukas http://www.rdfm.org/ammuzzu/
participants (1)
-
Claudio Bantaloukas