[PATCH] D70563: Use kevent queue for detecting file unlocking in LockFileManager
Paul Taykalo via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 21 14:39:10 PST 2019
PaulTaykalo added a comment.
This is the somewhat an example of program that is using kevent queue. additional timeouts are added to test cases such as deletion of the file right after the queue was created but notlistened yet.
Kevent testing program (Pass event for first parameter)
#include <iostream>
#include <sys/event.h>
#include <unistd.h>
#include <fcntl.h>
// Class that employs RAII to save a file descriptor
class FileDescriptorKeeper {
int FileDescriptor;
public:
FileDescriptorKeeper(int Descriptor) { FileDescriptor = Descriptor; }
~FileDescriptorKeeper() {
close(FileDescriptor);
std::cout << "File successfully closed" << std::endl;
}
};
bool ListenForAFileDeletion(char *path, int PID) {
int LockFileDescriptor;
int EventQueue;
// Opening file for lock descriptor
std::cout << "Opening file: " << path << std::endl;
if ((LockFileDescriptor = open(path, O_RDONLY)) == -1) {
std::cout << "[ERROR] File open error. The file was probably removed "
<< path << std::endl;
return false;
}
std::cout
<< "Will wait for 5 seconds to check if kqueu fails if file was deleted before event was added"
<< std::endl;
sleep(5);
FileDescriptorKeeper fileRAII = FileDescriptorKeeper(LockFileDescriptor);
std::cout << "Creating queue: " << std::endl;
if ((EventQueue = kqueue()) == -1) {
std::cout << "[ERROR] Queue cannot be created " << errno << std::endl;
return false;
}
FileDescriptorKeeper queueRAII = FileDescriptorKeeper(EventQueue);
int ListeningEventsCount = 2;
struct kevent ListeningEvents[2];
struct kevent *FileRemovingEvent = &ListeningEvents[0];
struct kevent *ProcessTerminationEvent = &ListeningEvents[1];
EV_SET(FileRemovingEvent, LockFileDescriptor, EVFILT_VNODE,
EV_ADD | EV_ENABLE | EV_ONESHOT | EV_CLEAR | EV_VANISHED |
EV_DISPATCH2, NOTE_DELETE, 0, 0);
EV_SET(ProcessTerminationEvent, PID, EVFILT_PROC,
EV_ADD | EV_ENABLE | EV_ONESHOT, NOTE_EXIT, 0, 0);
struct timespec timeout = {10, 0};
struct kevent ReceivedEvent;
int RegisteingResult =
kevent(EventQueue, ListeningEvents, ListeningEventsCount, NULL, 0,
NULL);
std::cout << "Registering events and start listening waiting for 5 sec"
<< RegisteingResult << std::endl;
sleep(5);
std::cout << "Listening event" << std::endl;
int ListeningResult =
kevent(EventQueue, NULL, 0, &ReceivedEvent, 1, &timeout);
// File was successfully deleted
if (ListeningResult > 0 && (ReceivedEvent.fflags & NOTE_DELETE &&
ReceivedEvent.filter == EVFILT_VNODE)) {
std::cout << "[OK] File was deleted: " << path << std::endl;
return true;
}
// Process owning the lock died
if (ListeningResult > 0 && (ReceivedEvent.fflags & NOTE_EXIT &&
ReceivedEvent.filter == EVFILT_PROC)) {
std::cout << "[OK] PID exited: " << path << std::endl;
return true;
}
if (ListeningResult < 0) {
std::cout << "[ERROR] Queue ended up with error" << errno << std::endl;
return false;
}
if (ListeningResult == 0) {
std::cout << "[OK] Queue has timed out" << std::endl;
return false;
}
std::cout << "[??] Unexpected event received" << ReceivedEvent.fflags << ":"
<< ReceivedEvent.filter << std::endl;
return false;
}
int main(int argc, char **argv) {
if (argc < 2) {
std::cout << "Please specify file to be deleted" << std::endl;
}
if (argc < 3) {
std::cout << "Please specify pid to be listened to" << std::endl;
}
char *FileName = argv[1];
int PID = atoi(argv[2]);
ListenForAFileDeletion(FileName, PID);
return 0;
}
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D70563/new/
https://reviews.llvm.org/D70563
More information about the llvm-commits
mailing list