chromium/third_party/mediapipe/src/mediapipe/framework/formats/unique_fd.h

#ifndef MEDIAPIPE_FRAMEWORK_FORMATS_ANDROID_UNIQUE_FD_H_
#define MEDIAPIPE_FRAMEWORK_FORMATS_ANDROID_UNIQUE_FD_H_

#include <unistd.h>

#include <utility>

#include "absl/base/attributes.h"
#include "absl/log/absl_log.h"

#if (__ANDROID_API__ >= 29) && defined(__BIONIC__) && !defined(NDEBUG)
#define MEDIAPIPE_USE_FDSAN 1
#include <android/fdsan.h>
#endif  // (__ANDROID_API__ >= 29) && defined(__BIONIC__) && !defined(NDEBUG)

namespace mediapipe {

// Implementation of a unique file descriptor wrapper inspired by
// https://android.googlesource.com/platform/bionic/+/master/docs/fdsan.md
//
// This class is a wrapper around a file descriptor that ensures that the
// descriptor is closed when the wrapper goes out of scope.
//
// This class is not thread-safe.
class UniqueFd {
 public:
  UniqueFd() = default;

  // Wraps and takes ownership of the given file descriptor.
  explicit UniqueFd(int fd) { Reset(fd); }

  UniqueFd(const UniqueFd& copy) = delete;
  UniqueFd(UniqueFd&& move) { *this = std::move(move); }

  // Closes the wrapped file descriptor during destruction if it is valid.
  ~UniqueFd() { Reset(); }

  UniqueFd& operator=(const UniqueFd& copy) = delete;
  UniqueFd& operator=(UniqueFd&& move) {
    if (this == &move) {
      return *this;
    }

    Reset();

    if (move.fd_ != -1) {
      fd_ = move.fd_;
      move.fd_ = -1;
#if defined(MEDIAPIPE_USE_FDSAN)
      // Acquire ownership from the moved-from object.
      FdsanExchangeTag(fd_, move.Tag(), Tag());
#endif  // MEDIAPIPE_USE_FDSAN
    }

    return *this;
  }

  // Returns a non-owned file descriptor.
  int Get() { return fd_; }

  // Checks if a valid file descriptor is wrapped.
  bool IsValid() const { return fd_ >= 0; }

  // Releases ownership of the file descriptor and returns it.
  ABSL_MUST_USE_RESULT int Release() {
    if (!IsValid()) {
      return -1;
    }

    int fd = fd_;
    fd_ = -1;
#if defined(MEDIAPIPE_USE_FDSAN)
    // Release ownership.
    FdsanExchangeTag(fd, Tag(), 0);
#endif  // MEDIAPIPE_USE_FDSAN
    return fd;
  }

  // Closes a wrapped file descriptor and resets the wrapper.
  void Reset(int new_fd = -1) {
    if (IsValid()) {
#if defined(MEDIAPIPE_USE_FDSAN)
      FdsanClose(fd_, Tag());
#else
      if (::close(fd_) != 0) {
        ABSL_LOG(ERROR) << "Failed to close fd: " << fd_;
      }
#endif  // MEDIAPIPE_USE_FDSAN
      fd_ = -1;
    }

    if (new_fd != -1) {
      fd_ = new_fd;
#if defined(MEDIAPIPE_USE_FDSAN)
      // Acquire ownership of the presumably unowned fd.
      FdsanExchangeTag(fd_, 0, Tag());
#endif  // MEDIAPIPE_USE_FDSAN
    }
  }

 private:
  int fd_ = -1;

#if defined(MEDIAPIPE_USE_FDSAN)
  // Address of the object is used as tag.
  uint64_t Tag() { return reinterpret_cast<uint64_t>(this); }

  // These functions are marked with __attribute__((weak)), so that their
  // availability can be determined at runtime. These wrappers will use them
  // if available, and fall back to no-ops or regular close on devices older
  // than API level 29 or non-bionic or non-production builds.
  static void FdsanExchangeTag(int fd, uint64_t old_tag, uint64_t new_tag) {
    if (android_fdsan_exchange_owner_tag) {
      android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
    }
  }

  static void FdsanClose(int fd, uint64_t tag) {
    if (android_fdsan_close_with_tag) {
      if (android_fdsan_close_with_tag(fd, tag) != 0) {
        ABSL_LOG(ERROR) << "Failed to close fd: " << fd;
      }
      return;
    }
    if (::close(fd) != 0) {
      ABSL_LOG(ERROR) << "Failed to close fd: " << fd;
    }
  }
#endif  // MEDIAPIPE_USE_FDSAN
};

}  // namespace mediapipe

#endif  // MEDIAPIPE_FRAMEWORK_FORMATS_ANDROID_UNIQUE_FD_H_