[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