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
|
#pragma once
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <fc/string.hpp>
|
#include <fc/string.hpp>
|
||||||
#include <fc/reflect/typename.hpp>
|
#include <fc/reflect/typename.hpp>
|
||||||
#include <fc/optional.hpp>
|
#include <fc/optional.hpp>
|
||||||
|
|
@ -226,5 +228,37 @@ namespace fc {
|
||||||
temp_directory(const fc::path& tempFolder = fc::temp_directory_path());
|
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/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
# ifdef FC_HAS_SIMPLE_FILE_LOCK
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace fc {
|
namespace fc {
|
||||||
|
|
@ -495,4 +499,101 @@ namespace fc {
|
||||||
return appCurrentPath;
|
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