C ++ Ubuntu не снимает блокировку файла блокировки после завершения

У меня есть сценарий C ++, который проверяет, должно ли быть выполнено какое-либо действие, и, если это так, запускает правильный сценарий C ++ процессора. Однако, поскольку он запускается каждые x минут, он также проверяет, не работает ли процессор с использованием файлов блокировки.

Я использую следующую функцию для получения блокировки:

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?)
}
}

Первый запуск работает хорошо, Однако, когда основной скрипт выполняется снова, файл блокировки возвращает -1, что означает, что произошла ошибка (только когда процессор все еще работает). Errno равно 11, что приводит к сообщению об ошибке: Resource temporarily unavailable, Обратите внимание, что это происходит только тогда, когда (зомби) процессор все еще работает. (Тем не менее, основной сценарий уже завершен, который должен закрыть дескриптор файла?)

Почему-то зомби держит дескриптор файла для файла блокировки основного скрипта открытым ???

Я понятия не имею, где искать эту проблему.

РЕШИТЬ:
смотри мой ответ

0

Решение

Нет 11 EAGAIN/EWOULDBLOCK это просто означает, что вы не можете получить блокировку, потому что ресурс уже заблокирован (см. документация). Вы получили эту ошибку (вместо блокировки поведения) из-за LOCK_NB флаг.

РЕДАКТИРОВАТЬ: После некоторого обсуждения кажется, что проблема связана с flock() блокировки сохраняются при обработке. Чтобы избежать этой проблемы, я рекомендую не использовать flock() на всю жизнь, но вместо этого прикасайтесь и удаляйте при выходе:

  1. Если file.lock существует тогда выход
  2. В противном случае создайте file.lock и начать обработку
  3. удалять file.lock на выходе.

Конечно, здесь есть условия гонки. Для обеспечения безопасности вам понадобится еще один файл с flock:

  1. flock(common.flock)
  2. Если file.lock существует тогда выход
  3. В противном случае создайте file.lock
  4. отпереть flock(common.flock)
  5. Начать обработку
  6. удалять 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 параллельно).

2

Другие решения

Я решил эту проблему, так как команды system и fork, похоже, передаются стаду, сохраняя команду для выполнения в векторе. Разблокируйте файл блокировки прямо перед циклом вектора Commands и выполните каждую команду. Это оставляет основной с очень маленьким промежутком бега, пока он не заблокирован, но сейчас он, кажется, работает отлично. Это также поддерживает неблагодарное завершение.

[...]
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());
}
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector