Add a simplified lock file class to use to prevent two applications from using the same resource
This commit is contained in:
parent
0642eb63d3
commit
a33bb60cf6
2 changed files with 135 additions and 0 deletions
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
#include <fc/string.hpp>
|
||||
#include <fc/reflect/typename.hpp>
|
||||
#include <fc/optional.hpp>
|
||||
|
|
@ -226,5 +228,37 @@ namespace fc {
|
|||
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
|
||||
};
|
||||
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
// this code is known to work on linux and windows. It may work correctly on mac,
|
||||
// or it may need slight tweaks or extra includes. It's disabled now to avoid giving
|
||||
// a false sense of security.
|
||||
# define FC_HAS_SIMPLE_FILE_LOCK
|
||||
#endif
|
||||
#ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||
/** simple class which only allows one process to open any given file.
|
||||
* approximate usage:
|
||||
* int main() {
|
||||
* fc::simple_file_lock instance_lock("~/.my_app/.lock");
|
||||
* if (!instance_lock.try_lock()) {
|
||||
* elog("my_app is already running");
|
||||
* return 1;
|
||||
* }
|
||||
* // do stuff here, file will be unlocked when instance_lock goes out of scope
|
||||
* }
|
||||
*/
|
||||
class simple_lock_file
|
||||
{
|
||||
public:
|
||||
simple_lock_file(const path& lock_file_path);
|
||||
~simple_lock_file();
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
private:
|
||||
class impl;
|
||||
std::unique_ptr<impl> my;
|
||||
};
|
||||
#endif // FC_HAS_SIMPLE_FILE_LOCK
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
# ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
namespace fc {
|
||||
|
|
@ -495,4 +499,101 @@ namespace fc {
|
|||
return appCurrentPath;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||
class simple_lock_file::impl
|
||||
{
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
HANDLE file_handle;
|
||||
#else
|
||||
int file_handle;
|
||||
#endif
|
||||
bool is_locked;
|
||||
path lock_file_path;
|
||||
|
||||
impl(const path& lock_file_path);
|
||||
~impl();
|
||||
|
||||
bool try_lock();
|
||||
void unlock();
|
||||
};
|
||||
|
||||
simple_lock_file::impl::impl(const path& lock_file_path) :
|
||||
is_locked(false),
|
||||
lock_file_path(lock_file_path),
|
||||
#ifdef _WIN32
|
||||
file_handle(INVALID_HANDLE_VALUE)
|
||||
#else
|
||||
file_handle(-1)
|
||||
#endif
|
||||
{}
|
||||
|
||||
simple_lock_file::impl::~impl()
|
||||
{
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool simple_lock_file::impl::try_lock()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
HANDLE fh = CreateFileA(lock_file_path.to_native_ansi_path().c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
0, 0,
|
||||
OPEN_ALWAYS, 0, NULL);
|
||||
if (fh == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
is_locked = true;
|
||||
file_handle = fh;
|
||||
return true;
|
||||
#else
|
||||
int fd = open(lock_file_path.string().c_str(), O_RDWR|O_CREAT, 0644);
|
||||
if (fd < 0)
|
||||
return false;
|
||||
if (flock(fd, LOCK_EX|LOCK_NB) == -1)
|
||||
{
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
is_locked = true;
|
||||
file_handle = fd;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void simple_lock_file::impl::unlock()
|
||||
{
|
||||
#ifdef WIN32
|
||||
CloseHandle(file_handle);
|
||||
file_handle = INVALID_HANDLE_VALUE;
|
||||
is_locked = false;
|
||||
#else
|
||||
flock(file_handle, LOCK_UN);
|
||||
close(file_handle);
|
||||
file_handle = -1;
|
||||
is_locked = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
simple_lock_file::simple_lock_file(const path& lock_file_path) :
|
||||
my(new impl(lock_file_path))
|
||||
{
|
||||
}
|
||||
|
||||
simple_lock_file::~simple_lock_file()
|
||||
{
|
||||
}
|
||||
|
||||
bool simple_lock_file::try_lock()
|
||||
{
|
||||
return my->try_lock();
|
||||
}
|
||||
|
||||
void simple_lock_file::unlock()
|
||||
{
|
||||
my->unlock();
|
||||
}
|
||||
#endif // FC_HAS_SIMPLE_FILE_LOCK
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue