blob: a62061e27368d54645831ce1265d869f7e2f4159 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "reference_drivers/os_handle.h"
#include <errno.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <unistd.h>
#include <utility>
#include "third_party/abseil-cpp/absl/base/macros.h"
namespace ipcz::reference_drivers {
OSHandle::OSHandle() = default;
OSHandle::OSHandle(Value value) : value_(value) {}
OSHandle::OSHandle(OSHandle&& other)
: value_(std::exchange(other.value_, {})) {}
OSHandle& OSHandle::operator=(OSHandle&& other) {
reset();
value_ = std::exchange(other.value_, {});
return *this;
}
OSHandle::~OSHandle() {
reset();
}
void OSHandle::reset() {
if (is_valid_fd()) {
int rv = close(fd());
ABSL_ASSERT(rv == 0 || errno == EINTR);
} else if (is_valid_mach_send_right()) {
kern_return_t kr =
mach_port_deallocate(mach_task_self(), mach_send_right());
ABSL_ASSERT(kr == KERN_SUCCESS);
} else if (is_valid_mach_receive_right()) {
kern_return_t kr = mach_port_mod_refs(
mach_task_self(), mach_receive_right(), MACH_PORT_RIGHT_RECEIVE, -1);
ABSL_ASSERT(kr == KERN_SUCCESS);
}
value_ = {};
}
OSHandle OSHandle::Clone() const {
ABSL_ASSERT(is_valid());
// Cloning of receive rights is not supported.
ABSL_ASSERT(!absl::holds_alternative<MachReceiveRight>(value_));
if (is_valid_fd()) {
int duped_fd = dup(fd());
ABSL_ASSERT(duped_fd >= 0);
return OSHandle(FileDescriptor(duped_fd));
}
if (is_valid_mach_send_right()) {
kern_return_t kr = mach_port_mod_refs(mach_task_self(), mach_send_right(),
MACH_PORT_RIGHT_SEND, 1);
if (kr != KERN_SUCCESS) {
return OSHandle();
}
return OSHandle(MachSendRight(mach_send_right()));
}
return {};
}
} // namespace ipcz::reference_drivers