From 23e20d6833c30e90ee4dbc117880a5d7abf37fcc Mon Sep 17 00:00:00 2001 From: Jonathan Bendes Date: Sat, 15 Aug 2020 12:25:51 -0400 Subject: [PATCH] Fixed up lockfile --- zcm/transport/transport_file.cpp | 1 - zcm/transport/transport_serial.cpp | 16 ++++-- zcm/transport/transport_zmq_local.cpp | 19 ++++--- zcm/util/lockfile.cpp | 76 ++++++++++----------------- zcm/util/lockfile.h | 13 ++++- 5 files changed, 62 insertions(+), 63 deletions(-) diff --git a/zcm/transport/transport_file.cpp b/zcm/transport/transport_file.cpp index c71a143f..65b5243c 100644 --- a/zcm/transport/transport_file.cpp +++ b/zcm/transport/transport_file.cpp @@ -4,7 +4,6 @@ #include "zcm/zcm-cpp.hpp" #include "zcm/util/debug.h" -//#include "zcm/util/lockfile.h" #include "util/Types.hpp" #include "util/TimeUtil.hpp" diff --git a/zcm/transport/transport_serial.cpp b/zcm/transport/transport_serial.cpp index 764ef502..5220855a 100644 --- a/zcm/transport/transport_serial.cpp +++ b/zcm/transport/transport_serial.cpp @@ -65,6 +65,7 @@ struct Serial private: string port; int fd = -1; + lockfile_t* lf; }; bool Serial::open(const string& port_, int baud, bool hwFlowControl) @@ -77,7 +78,8 @@ bool Serial::open(const string& port_, int baud, bool hwFlowControl) return false; } - if (!lockfile_trylock(port_.c_str())) { + lf = lockfile_trylock(port_.c_str()); + if (!lf) { ZCM_DEBUG("failed to create lock file, refusing to open serial device (%s)", port_.c_str()); return false; @@ -141,7 +143,10 @@ bool Serial::open(const string& port_, int baud, bool hwFlowControl) this->fd = -1; // Unlock the lock file - if (port != "") lockfile_unlock(port.c_str()); + if (lf) { + lockfile_unlock(lf); + lf = nullptr; + } this->port = ""; return false; @@ -154,9 +159,10 @@ void Serial::close() ::close(fd); fd = 0; } - if (port != "") { - lockfile_unlock(port.c_str()); - port = ""; + if (port != "") port = ""; + if (lf) { + lockfile_unlock(lf); + lf = nullptr; } } diff --git a/zcm/transport/transport_zmq_local.cpp b/zcm/transport/transport_zmq_local.cpp index fc9eff7e..3336f75c 100644 --- a/zcm/transport/transport_zmq_local.cpp +++ b/zcm/transport/transport_zmq_local.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,7 @@ struct ZCM_TRANS_CLASSNAME : public zcm_trans_t string subnet; - unordered_map pubsocks; + unordered_map> pubsocks; // socket pair contains the socket + whether it was subscribed to explicitly or not unordered_map> subsocks; bool recvAllChannels = false; @@ -83,17 +84,17 @@ struct ZCM_TRANS_CLASSNAME : public zcm_trans_t for (auto it = pubsocks.begin(); it != pubsocks.end(); ++it) { address = getAddress(it->first); - rc = zmq_unbind(it->second, address.c_str()); + rc = zmq_unbind(it->second.first, address.c_str()); if (rc == -1) { ZCM_DEBUG("failed to unbind pubsock: %s", zmq_strerror(errno)); } - rc = zmq_close(it->second); + rc = zmq_close(it->second.first); if (rc == -1) { ZCM_DEBUG("failed to close pubsock: %s", zmq_strerror(errno)); } - lockfile_unlock(address.c_str()); + lockfile_unlock(it->second.second); } // Clean up all subscribe sockets @@ -136,9 +137,10 @@ struct ZCM_TRANS_CLASSNAME : public zcm_trans_t { auto it = pubsocks.find(channel); if (it != pubsocks.end()) - return it->second; + return it->second.first; // Before we create a pubsock, we need to acquire the lock file for this - if (!lockfile_trylock(getAddress(channel).c_str())) { + lockfile_t *lf = lockfile_trylock(getAddress(channel).c_str()); + if (!lf) { fprintf(stderr, "Failed to acquire publish lock on %s! " "Are you attempting multiple publishers?\n", channel.c_str()); @@ -147,15 +149,18 @@ struct ZCM_TRANS_CLASSNAME : public zcm_trans_t void *sock = zmq_socket(ctx, ZMQ_PUB); if (sock == nullptr) { ZCM_DEBUG("failed to create pubsock: %s", zmq_strerror(errno)); + lockfile_unlock(lf); return nullptr; } string address = getAddress(channel); int rc = zmq_bind(sock, address.c_str()); if (rc == -1) { ZCM_DEBUG("failed to bind pubsock: %s", zmq_strerror(errno)); + lockfile_unlock(lf); return nullptr; } - pubsocks.emplace(channel, sock); + pair p {sock, lf}; + pubsocks.emplace(channel, p); return sock; } diff --git a/zcm/util/lockfile.cpp b/zcm/util/lockfile.cpp index 5ecac5fa..edbddc57 100644 --- a/zcm/util/lockfile.cpp +++ b/zcm/util/lockfile.cpp @@ -1,24 +1,22 @@ #include "zcm/util/lockfile.h" #include "zcm/util/debug.h" +#include +#include +#include +#include #include -#include +#include #include -#include -#include +#include #include -#include +#include -#include -#include using namespace std; #define DEFAULT_LOCK_DIR "/var/lock/zcm" #define LOCK_PREFIX "LCK.." -#include -static unordered_map fds; - static bool startsWith(const string& s, const string& pre) { if (s.size() < pre.size()) @@ -61,58 +59,40 @@ static string makeLockfilePath(const string& name) return ret; } -static int openLockfile(const string& name) +lockfile_t* lockfile_trylock(const char *name) { - if (!fds.count(name)) { - auto path = makeLockfilePath(name); - int fd = open(path.c_str(), O_WRONLY | O_CREAT, 0666); - if (fd < 0) return -1; - fds[name] = fd; - } - return fds[name]; -} - -static bool isLocked(const string& name) -{ - int fd = openLockfile(name); - if (fd < 0) return true; - - int ret = lockf(fd, F_TEST, 0); - - return ret == 0; -} - - -bool lockfile_trylock(const char *name) -{ - int fd = openLockfile(name); + auto path = makeLockfilePath(name); + int fd = open(path.c_str(), O_WRONLY | O_CREAT, 0666); if (fd < 0) { ZCM_DEBUG("Unable to open lockfile: '%s'", name); - return false; + return nullptr; } - int ret = lockf(fd, F_TLOCK, 0); - if (ret < 0) { + int lkRet = lockf(fd, F_TLOCK, 0); + if (lkRet < 0) { ZCM_DEBUG("Failed to lock lockfile '%s'. Error: %s", name, strerror(errno)); - return false; + close(fd); + return nullptr; } - return true; + lockfile_t *ret = new lockfile_t; + ret->fd = fd; + ret->name = strdup(name); + return ret; } -void lockfile_unlock(const char *name) +void lockfile_unlock(lockfile_t* lf) { - int fd = openLockfile(name); - if (fd < 0) return; - - int ret = lockf(fd, F_ULOCK, 0); + int ret = lockf(lf->fd, F_ULOCK, 0); if (ret < 0) - ZCM_DEBUG("Failed to unlock lockfile '%s'. Error: %s", name, strerror(errno)); + ZCM_DEBUG("Failed to unlock lockfile '%s'. Error: %s", lf->name, strerror(errno)); - close(fd); - fds.erase(name); + close(lf->fd); - int err = unlink(makeLockfilePath(name).c_str()); + int err = unlink(makeLockfilePath(lf->name).c_str()); if (err < 0) - ZCM_DEBUG("Failed to unlink lockfile '%s'. Error: %s", name, strerror(errno)); + ZCM_DEBUG("Failed to unlink lockfile '%s'. Error: %s", lf->name, strerror(errno)); + + free(lf->name); + delete lf; } diff --git a/zcm/util/lockfile.h b/zcm/util/lockfile.h index 608346f7..a2de74de 100644 --- a/zcm/util/lockfile.h +++ b/zcm/util/lockfile.h @@ -15,8 +15,17 @@ extern "C" { #endif -bool lockfile_trylock(const char *name); -void lockfile_unlock(const char *name); +typedef struct +{ + int fd; + char* name; +} lockfile_t; + +// returns < 0 if failed to acquire lockfile +lockfile_t* lockfile_trylock(const char *name); + +// lf gets destroyed after call to unlock +void lockfile_unlock(lockfile_t* lf); #ifdef __cplusplus }