C++ Ubuntu 终止时不释放对锁定文件的锁定
C++ Ubuntu not releasing lock on lock file when terminated
我有一个 C++ 脚本,它检查是否需要执行任何操作,如果需要,它会启动正确的处理器 C++ 脚本。但是,由于它每 x 分钟 运行s,它还会检查处理器是否仍在 运行ning 使用锁定文件。
我使用以下函数获取锁:
int LockFile(string FileNameToLock) {
FileNameToLock += ".lock";
int fd = open(FileNameToLock.c_str(), O_RDWR | O_CREAT, 0666);
int rc = flock(fd, LOCK_EX | LOCK_NB);
if (rc || rc == -1) {
cout << errno << endl;
cout << strerror(errno) << endl;
return -1;
}
return fd;
}
正在执行的代码:
[...]
if (LockFile(ExecuteFileName, Extra) == -1) {
cout << "Already running!" << endl; //MAIN IS ALREADY RUNNING
//RETURNS ME Resource temporarily unavailable when processor is running from an earlier run
exit(EXIT_SUCCESS);
}
if (StartProcessor) { //PSEUDO
int LockFileProcessor = LockFile("Processor");
if (LockFileProcessor != -1) {
string Command = "nohup setsid ./Processor"; //NOHUP CREATES ZOMBIE?
Command += IntToString(result->getInt("Klantnummer"));
Command += " > /dev/null 2>&1 &"; //DISCARD OUTPUT
system(Command.c_str());
//STARTS PROCESSOR (AS ZOMBIE?)
}
}
第一个运行运行良好,但是当主脚本运行s 又,锁定文件returns-1,表示发生错误(仅当处理器还在运行ning时)。 errno 是 11,这会导致错误消息:Resource temporarily unavailable
。 请注意,这仅在(僵尸)处理器仍在 运行ning 时发生。 (但是,主脚本已经终止,应该关闭文件句柄?)
出于某种原因,僵尸保持打开主脚本的锁定文件的文件句柄???
我不知道去哪里找这个问题。
已解决:
看我的回答
不,11 是 EAGAIN/EWOULDBLOCK
,这仅表示您无法获取锁,因为资源已被锁定(请参阅 the documentation)。由于 LOCK_NB
标志,您收到了该错误(而不是阻止行为)。
编辑: 经过一番讨论,问题似乎是由于子处理时 flock()
锁被保留所致。为避免此问题,我建议在整个生命周期内不要使用 flock()
,而是使用触摸并删除退出策略:
- 如果
file.lock
存在则退出
- 否则创建
file.lock
并开始处理
- 在退出时删除
file.lock
。
这里当然存在竞争条件。为了确保安全,您需要另一个包含 flock
:
的文件
flock(common.flock)
- 如果
file.lock
存在则退出
- 否则创建
file.lock
- 解锁
flock(common.flock)
- 开始处理
- 在退出时删除
file.lock
但这仅在您希望同时调用 main
时才有意义。如果你不这样做(你说 cron 每 10 分钟启动一次进程,这里没有竞争)然后坚持第一个版本。
旁注:这是此类(非同步)文件锁的简单实现:
#include <string>
#include <fstream>
#include <stdexcept>
#include <cstdio>
// for sleep only
#include <chrono>
#include <thread>
class FileLock {
public:
FileLock(const std::string& path) : path { path } {
if (std::ifstream{ path }) {
// You may want to use a custom exception here
throw std::runtime_error("Already locked.");
}
std::ofstream file{ path };
};
~FileLock() {
std::remove(path.c_str());
};
private:
std::string path;
};
int main() {
// This will throw std::runtime_error if test.xxx exists
FileLock fl { "./test.xxx" };
std::this_thread::sleep_for(std::chrono::seconds { 5 });
// RAII: no need to delete anything here
return 0;
};
需要 C++11。请注意,此实现不是竞争条件安全的,即您通常需要 flock()
构造函数,但在这种情况下它可能没问题(即当您不并行启动 main 时)。
我解决了这个问题,因为 system 和 fork 命令似乎在群中传递,方法是保存要在向量中执行的命令。在循环命令向量之前解锁锁定文件并执行每个命令。这使得 main 在未锁定时有一个非常小的 运行 间隙,但现在它似乎工作得很好。这也支持非正常终止。
[...]
if (LockFile(ExecuteFileName, Extra) == -1) {
cout << "Already running!" << endl; //MAIN IS ALREADY RUNNING
//RETURNS ME Resource temporarily unavailable when processor is running from an earlier run
exit(EXIT_SUCCESS);
}
vector<string> Commands;
if (StartProcessor) { //PSEUDO
int LockFileProcessor = LockFile("Processor");
if (LockFileProcessor != -1) {
string Command = "nohup setsid ./Processor"; //NOHUP CREATES ZOMBIE
Command += IntToString(result->getInt("Klantnummer"));
Command += " > /dev/null 2>&1 &"; //DISCARD OUTPUT
Commands.push_back(Command);
}
}
//UNLOCK MAIN
if (UnlockFile(LockFileMain)) {
for(auto const& Command: Commands) {
system(Command.c_str());
}
}
我有一个 C++ 脚本,它检查是否需要执行任何操作,如果需要,它会启动正确的处理器 C++ 脚本。但是,由于它每 x 分钟 运行s,它还会检查处理器是否仍在 运行ning 使用锁定文件。
我使用以下函数获取锁:
int LockFile(string FileNameToLock) {
FileNameToLock += ".lock";
int fd = open(FileNameToLock.c_str(), O_RDWR | O_CREAT, 0666);
int rc = flock(fd, LOCK_EX | LOCK_NB);
if (rc || rc == -1) {
cout << errno << endl;
cout << strerror(errno) << endl;
return -1;
}
return fd;
}
正在执行的代码:
[...]
if (LockFile(ExecuteFileName, Extra) == -1) {
cout << "Already running!" << endl; //MAIN IS ALREADY RUNNING
//RETURNS ME Resource temporarily unavailable when processor is running from an earlier run
exit(EXIT_SUCCESS);
}
if (StartProcessor) { //PSEUDO
int LockFileProcessor = LockFile("Processor");
if (LockFileProcessor != -1) {
string Command = "nohup setsid ./Processor"; //NOHUP CREATES ZOMBIE?
Command += IntToString(result->getInt("Klantnummer"));
Command += " > /dev/null 2>&1 &"; //DISCARD OUTPUT
system(Command.c_str());
//STARTS PROCESSOR (AS ZOMBIE?)
}
}
第一个运行运行良好,但是当主脚本运行s 又,锁定文件returns-1,表示发生错误(仅当处理器还在运行ning时)。 errno 是 11,这会导致错误消息:Resource temporarily unavailable
。 请注意,这仅在(僵尸)处理器仍在 运行ning 时发生。 (但是,主脚本已经终止,应该关闭文件句柄?)
出于某种原因,僵尸保持打开主脚本的锁定文件的文件句柄???
我不知道去哪里找这个问题。
已解决: 看我的回答
不,11 是 EAGAIN/EWOULDBLOCK
,这仅表示您无法获取锁,因为资源已被锁定(请参阅 the documentation)。由于 LOCK_NB
标志,您收到了该错误(而不是阻止行为)。
编辑: 经过一番讨论,问题似乎是由于子处理时 flock()
锁被保留所致。为避免此问题,我建议在整个生命周期内不要使用 flock()
,而是使用触摸并删除退出策略:
- 如果
file.lock
存在则退出 - 否则创建
file.lock
并开始处理 - 在退出时删除
file.lock
。
这里当然存在竞争条件。为了确保安全,您需要另一个包含 flock
:
flock(common.flock)
- 如果
file.lock
存在则退出 - 否则创建
file.lock
- 解锁
flock(common.flock)
- 开始处理
- 在退出时删除
file.lock
但这仅在您希望同时调用 main
时才有意义。如果你不这样做(你说 cron 每 10 分钟启动一次进程,这里没有竞争)然后坚持第一个版本。
旁注:这是此类(非同步)文件锁的简单实现:
#include <string>
#include <fstream>
#include <stdexcept>
#include <cstdio>
// for sleep only
#include <chrono>
#include <thread>
class FileLock {
public:
FileLock(const std::string& path) : path { path } {
if (std::ifstream{ path }) {
// You may want to use a custom exception here
throw std::runtime_error("Already locked.");
}
std::ofstream file{ path };
};
~FileLock() {
std::remove(path.c_str());
};
private:
std::string path;
};
int main() {
// This will throw std::runtime_error if test.xxx exists
FileLock fl { "./test.xxx" };
std::this_thread::sleep_for(std::chrono::seconds { 5 });
// RAII: no need to delete anything here
return 0;
};
需要 C++11。请注意,此实现不是竞争条件安全的,即您通常需要 flock()
构造函数,但在这种情况下它可能没问题(即当您不并行启动 main 时)。
我解决了这个问题,因为 system 和 fork 命令似乎在群中传递,方法是保存要在向量中执行的命令。在循环命令向量之前解锁锁定文件并执行每个命令。这使得 main 在未锁定时有一个非常小的 运行 间隙,但现在它似乎工作得很好。这也支持非正常终止。
[...]
if (LockFile(ExecuteFileName, Extra) == -1) {
cout << "Already running!" << endl; //MAIN IS ALREADY RUNNING
//RETURNS ME Resource temporarily unavailable when processor is running from an earlier run
exit(EXIT_SUCCESS);
}
vector<string> Commands;
if (StartProcessor) { //PSEUDO
int LockFileProcessor = LockFile("Processor");
if (LockFileProcessor != -1) {
string Command = "nohup setsid ./Processor"; //NOHUP CREATES ZOMBIE
Command += IntToString(result->getInt("Klantnummer"));
Command += " > /dev/null 2>&1 &"; //DISCARD OUTPUT
Commands.push_back(Command);
}
}
//UNLOCK MAIN
if (UnlockFile(LockFileMain)) {
for(auto const& Command: Commands) {
system(Command.c_str());
}
}