#include <string>
#include <stdexcept>
#include <iostream>
#include <cassert>
#include <thread>
#include <chrono>
#include <cstdlib>
#include <unistd.h>
#include <sys/file.h>
#include <sys/stat.h>
struct FileLock
{
std::string _path;
FileLock(const std::string& p, bool acq = false)
: _path(p)
{
if (acq)
{
bool r = acquire();
if (!r) throw std::runtime_error("FileLock::acquire failed");
}
}
~FileLock()
{
bool r = release();
if (!r) std::cerr << "FileLock::release failed";
}
const char* path() const {return _path.c_str();}
// #############################################################################
#define CHECK_OK_(v, pred) \
{ \
bool res = (pred); \
if (!res) std::cerr<< ("FileLock: (" #pred ") = false"); \
v &= res; \
}
bool acquire()
{
bool ok = true;
int r;
// auto fp = std::fopen(_path.c_str(), "w");
// if (!fp)
// return false;
// int fd = ::fileno(fp);
auto m = umask(0);
int fd = ::open(_path.c_str(), O_RDWR | O_CREAT, 0666);
umask(m);
CHECK_OK_(ok, fd != -1);
if (ok)
{
r = ::flock(fd, LOCK_EX | LOCK_NB);
CHECK_OK_(ok, r != -1);
if (ok)
{ // write pid
pid_t pid = getpid();
auto pstr = std::to_string(pid);
auto wr = ::write(fd, pstr.c_str(), pstr.size());
CHECK_OK_(ok, wr == pstr.size());
}
}
// CHECK_OK_(ok, std::fclose(fp) == 0);
CHECK_OK_(ok, ::close(fd) == 0);
return ok;
}
// #############################################################################
bool release()
{
bool ok = true;
// auto fp = std::fopen(_path.c_str(), "r");
// if (!fp)
// return false;
// int fd = ::fileno(fp);
int fd = ::open(_path.c_str(), O_RDONLY);
CHECK_OK_(ok, fd != -1);
if (ok)
{
int r = ::flock(fd, LOCK_UN | LOCK_NB);
CHECK_OK_(ok, r != -1);
}
// pid should == getpid()
// CHECK_OK_(ok, std::fclose(fp) == 0);
CHECK_OK_(ok, ::close(fd) == 0);
// necessary?
CHECK_OK_(ok, std::remove(_path.c_str()) != -1);
return ok;
}
#undef CHECK_OK_
};
int main(int ac, const char* av[])
{
assert((ac >= 2) && "usage: prog file_name");
FileLock fl(av[1], true);
while (1)
{
std::this_thread::sleep_for(std::chrono::seconds{1});
std::cout << "waiting... \n";
}
}
I2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHN0ZGV4Y2VwdD4KI2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y2Fzc2VydD4KI2luY2x1ZGUgPHRocmVhZD4KI2luY2x1ZGUgPGNocm9ubz4KCiNpbmNsdWRlIDxjc3RkbGliPgojaW5jbHVkZSA8dW5pc3RkLmg+CiNpbmNsdWRlIDxzeXMvZmlsZS5oPgojaW5jbHVkZSA8c3lzL3N0YXQuaD4KCnN0cnVjdCBGaWxlTG9jawogIHsKICBzdGQ6OnN0cmluZyBfcGF0aDsKCiAgRmlsZUxvY2soY29uc3Qgc3RkOjpzdHJpbmcmIHAsIGJvb2wgYWNxID0gZmFsc2UpCiAgICA6IF9wYXRoKHApCiAgICB7CiAgICBpZiAoYWNxKQogICAgICB7CiAgICAgIGJvb2wgciA9IGFjcXVpcmUoKTsKICAgICAgaWYgKCFyKSB0aHJvdyBzdGQ6OnJ1bnRpbWVfZXJyb3IoIkZpbGVMb2NrOjphY3F1aXJlIGZhaWxlZCIpOwogICAgICB9CiAgICB9CgogIH5GaWxlTG9jaygpCiAgICB7CiAgICBib29sIHIgPSByZWxlYXNlKCk7CiAgICBpZiAoIXIpIHN0ZDo6Y2VyciA8PCAiRmlsZUxvY2s6OnJlbGVhc2UgZmFpbGVkIjsKICAgIH0KICAKICBjb25zdCBjaGFyKiBwYXRoKCkgY29uc3Qge3JldHVybiBfcGF0aC5jX3N0cigpO30KICAKICAvLyAjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIwoKI2RlZmluZSBDSEVDS19PS18odiwgcHJlZCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKICBib29sIHJlcyA9IChwcmVkKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXAogIGlmICghcmVzKSBzdGQ6OmNlcnI8PCAoIkZpbGVMb2NrOiAoIiAjcHJlZCAiKSA9IGZhbHNlIik7ICAgXAogIHYgJj0gcmVzOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgfQogIAogIGJvb2wgYWNxdWlyZSgpCiAgICB7CiAgICBib29sIG9rID0gdHJ1ZTsKICAgIGludCByOwogICAgCiAgICAvLyBhdXRvIGZwID0gc3RkOjpmb3BlbihfcGF0aC5jX3N0cigpLCAidyIpOwogICAgLy8gaWYgKCFmcCkKICAgIC8vICAgcmV0dXJuIGZhbHNlOwoKICAgIC8vIGludCBmZCA9IDo6ZmlsZW5vKGZwKTsKCiAgICBhdXRvIG0gPSB1bWFzaygwKTsKICAgIGludCBmZCA9IDo6b3BlbihfcGF0aC5jX3N0cigpLCBPX1JEV1IgfCBPX0NSRUFULCAwNjY2KTsKICAgIHVtYXNrKG0pOwogICAgCiAgICBDSEVDS19PS18ob2ssIGZkICE9IC0xKTsKICAgIGlmIChvaykKICAgICAgewogICAgICByID0gOjpmbG9jayhmZCwgTE9DS19FWCB8IExPQ0tfTkIpOwogICAgICBDSEVDS19PS18ob2ssIHIgIT0gLTEpOwogICAgICBpZiAob2spCiAgICAgICAgeyAgICAgICAgICAgICAgICAgICAgICAgLy8gd3JpdGUgcGlkCiAgICAgICAgcGlkX3QgcGlkID0gZ2V0cGlkKCk7CiAgICAgICAgYXV0byBwc3RyID0gc3RkOjp0b19zdHJpbmcocGlkKTsKICAgICAgICBhdXRvIHdyID0gOjp3cml0ZShmZCwgcHN0ci5jX3N0cigpLCBwc3RyLnNpemUoKSk7CiAgICAgICAgQ0hFQ0tfT0tfKG9rLCB3ciA9PSBwc3RyLnNpemUoKSk7CiAgICAgICAgfQogICAgICB9CiAgICAKICAgIC8vIENIRUNLX09LXyhvaywgIHN0ZDo6ZmNsb3NlKGZwKSA9PSAwKTsKICAgIENIRUNLX09LXyhvaywgOjpjbG9zZShmZCkgPT0gMCk7CiAgICAKICAgIHJldHVybiBvazsKICAgIH0KCiAgLy8gIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMKICAKICBib29sIHJlbGVhc2UoKQogICAgewogICAgYm9vbCBvayA9IHRydWU7CiAgICAKICAgIC8vIGF1dG8gZnAgPSBzdGQ6OmZvcGVuKF9wYXRoLmNfc3RyKCksICJyIik7CiAgICAvLyBpZiAoIWZwKQogICAgLy8gICByZXR1cm4gZmFsc2U7CiAgICAKICAgIC8vIGludCBmZCA9IDo6ZmlsZW5vKGZwKTsKICAgIAogICAgaW50IGZkID0gOjpvcGVuKF9wYXRoLmNfc3RyKCksIE9fUkRPTkxZKTsKICAgIENIRUNLX09LXyhvaywgZmQgIT0gLTEpOwogICAgaWYgKG9rKQogICAgICB7CiAgICAgIGludCByID0gOjpmbG9jayhmZCwgTE9DS19VTiB8IExPQ0tfTkIpOwogICAgICBDSEVDS19PS18ob2ssIHIgIT0gLTEpOwogICAgICB9CiAgICAgIAogICAgLy8gcGlkIHNob3VsZCA9PSBnZXRwaWQoKQogICAgICAKICAgIC8vIENIRUNLX09LXyhvaywgc3RkOjpmY2xvc2UoZnApID09IDApOwogICAgQ0hFQ0tfT0tfKG9rLCA6OmNsb3NlKGZkKSA9PSAwKTsKCiAgICAvLyBuZWNlc3Nhcnk/CiAgICBDSEVDS19PS18ob2ssIHN0ZDo6cmVtb3ZlKF9wYXRoLmNfc3RyKCkpICE9IC0xKTsKICAgIAogICAgcmV0dXJuIG9rOwogICAgfQoKI3VuZGVmIENIRUNLX09LXwogICAgICAKICB9OwoKaW50IG1haW4oaW50IGFjLCBjb25zdCBjaGFyKiBhdltdKQp7CiAgYXNzZXJ0KChhYyA+PSAyKSAmJiAidXNhZ2U6IHByb2cgZmlsZV9uYW1lIik7CgogIEZpbGVMb2NrIGZsKGF2WzFdLCB0cnVlKTsKCiAgd2hpbGUgKDEpCiAgewogICAgc3RkOjp0aGlzX3RocmVhZDo6c2xlZXBfZm9yKHN0ZDo6Y2hyb25vOjpzZWNvbmRzezF9KTsKICAgIHN0ZDo6Y291dCA8PCAid2FpdGluZy4uLiBcbiI7CiAgfQp9Cg==