From 35dc1fc5893881946e94877a2edf8940a89a3105 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 23 Jan 2025 16:47:13 +0100 Subject: [PATCH] io/UniqueFileDescriptor: use AdoptTag in the constructors that adopt ownership --- src/event/InotifyEvent.cxx | 2 +- src/io/FileDescriptor.cxx | 2 +- src/io/UniqueFileDescriptor.hxx | 5 +- src/net/SocketDescriptor.cxx | 2 +- src/net/UniqueSocketDescriptor.hxx | 2 +- src/net/UniqueSocketDescriptor.hxx.orig | 105 ++++++++++++++++++++++++ src/system/EpollFD.cxx | 2 +- src/system/EventFD.cxx | 2 +- src/system/SignalFD.cxx | 2 +- 9 files changed, 115 insertions(+), 9 deletions(-) create mode 100644 src/net/UniqueSocketDescriptor.hxx.orig diff --git a/src/event/InotifyEvent.cxx b/src/event/InotifyEvent.cxx index e8f92533db..38ff72b7ed 100644 --- a/src/event/InotifyEvent.cxx +++ b/src/event/InotifyEvent.cxx @@ -18,7 +18,7 @@ CreateInotify() if (fd < 0) throw MakeErrno("inotify_init1() failed"); - return UniqueFileDescriptor(fd); + return UniqueFileDescriptor(AdoptTag{}, fd); } InotifyEvent::InotifyEvent(EventLoop &event_loop, InotifyHandler &_handler) diff --git a/src/io/FileDescriptor.cxx b/src/io/FileDescriptor.cxx index bd900d3f0e..95250fc299 100644 --- a/src/io/FileDescriptor.cxx +++ b/src/io/FileDescriptor.cxx @@ -225,7 +225,7 @@ FileDescriptor::SetPipeCapacity(unsigned capacity) const noexcept UniqueFileDescriptor FileDescriptor::Duplicate() const noexcept { - return UniqueFileDescriptor{::dup(Get())}; + return UniqueFileDescriptor{AdoptTag{}, ::dup(Get())}; } bool diff --git a/src/io/UniqueFileDescriptor.hxx b/src/io/UniqueFileDescriptor.hxx index 1e2aec8b80..657b6d9692 100644 --- a/src/io/UniqueFileDescriptor.hxx +++ b/src/io/UniqueFileDescriptor.hxx @@ -4,6 +4,7 @@ #pragma once #include "FileDescriptor.hxx" // IWYU pragma: export +#include "util/TagStructs.hxx" #include #include @@ -16,10 +17,10 @@ public: UniqueFileDescriptor() noexcept :FileDescriptor(FileDescriptor::Undefined()) {} - explicit UniqueFileDescriptor(int _fd) noexcept + explicit UniqueFileDescriptor(AdoptTag, int _fd) noexcept :FileDescriptor(_fd) {} - explicit UniqueFileDescriptor(FileDescriptor _fd) noexcept + explicit UniqueFileDescriptor(AdoptTag, FileDescriptor _fd) noexcept :FileDescriptor(_fd) {} UniqueFileDescriptor(const UniqueFileDescriptor &) = delete; diff --git a/src/net/SocketDescriptor.cxx b/src/net/SocketDescriptor.cxx index 6ffb5de53a..64664e1337 100644 --- a/src/net/SocketDescriptor.cxx +++ b/src/net/SocketDescriptor.cxx @@ -252,7 +252,7 @@ SocketDescriptor::GetPeerPidfd() const noexcept if (GetOption(SOL_SOCKET, SO_PEERPIDFD, &pidfd, sizeof(pidfd)) < sizeof(pidfd)) return {}; - return UniqueFileDescriptor{pidfd}; + return UniqueFileDescriptor{AdoptTag{}, pidfd}; } #endif // __linux__ diff --git a/src/net/UniqueSocketDescriptor.hxx b/src/net/UniqueSocketDescriptor.hxx index 70bf45834f..76e09c2b7e 100644 --- a/src/net/UniqueSocketDescriptor.hxx +++ b/src/net/UniqueSocketDescriptor.hxx @@ -58,7 +58,7 @@ public: #ifndef _WIN32 UniqueFileDescriptor MoveToFileDescriptor() && noexcept { - return UniqueFileDescriptor{Release().ToFileDescriptor()}; + return UniqueFileDescriptor{AdoptTag{}, Release().ToFileDescriptor()}; } #endif diff --git a/src/net/UniqueSocketDescriptor.hxx.orig b/src/net/UniqueSocketDescriptor.hxx.orig new file mode 100644 index 0000000000..c745487369 --- /dev/null +++ b/src/net/UniqueSocketDescriptor.hxx.orig @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-2-Clause +// author: Max Kellermann + +#pragma once + +#include "SocketDescriptor.hxx" + +#ifndef _WIN32 +#include "io/UniqueFileDescriptor.hxx" +#endif + +#include + +class StaticSocketAddress; + +/** + * Wrapper for a socket file descriptor. + */ +class UniqueSocketDescriptor : public SocketDescriptor { +public: + UniqueSocketDescriptor() noexcept + :SocketDescriptor(SocketDescriptor::Undefined()) {} + + explicit UniqueSocketDescriptor(SocketDescriptor _fd) noexcept + :SocketDescriptor(_fd) {} +#ifndef _WIN32 + explicit UniqueSocketDescriptor(FileDescriptor _fd) noexcept + :SocketDescriptor(_fd) {} + + explicit UniqueSocketDescriptor(UniqueFileDescriptor &&_fd) noexcept + :SocketDescriptor(_fd.Release()) {} +#endif // !_WIN32 + + explicit UniqueSocketDescriptor(int _fd) noexcept + :SocketDescriptor(_fd) {} + +#ifdef _WIN32 + UniqueSocketDescriptor(UniqueSocketDescriptor &&other) noexcept + :SocketDescriptor(std::exchange(other.fd, INVALID_SOCKET)) {} +#else // !_WIN32 + UniqueSocketDescriptor(UniqueSocketDescriptor &&other) noexcept + :SocketDescriptor(std::exchange(other.fd, -1)) {} +#endif // !_WIN32 + + ~UniqueSocketDescriptor() noexcept { + if (IsDefined()) + Close(); + } + + /** + * Release ownership and return the descriptor as an unmanaged + * #SocketDescriptor instance. + */ + SocketDescriptor Release() noexcept { + return std::exchange(*(SocketDescriptor *)this, Undefined()); + } + +#ifndef _WIN32 + UniqueFileDescriptor MoveToFileDescriptor() && noexcept { + return UniqueFileDescriptor{Release().ToFileDescriptor()}; + } +#endif + + UniqueSocketDescriptor &operator=(UniqueSocketDescriptor &&src) noexcept { + using std::swap; + swap(fd, src.fd); + return *this; + } + + bool operator==(const UniqueSocketDescriptor &other) const noexcept { + return fd == other.fd; + } + + /** + * @return an "undefined" instance on error + */ + UniqueSocketDescriptor AcceptNonBlock() const noexcept { + return UniqueSocketDescriptor(SocketDescriptor::AcceptNonBlock()); + } + + /** + * @return an "undefined" instance on error + */ + UniqueSocketDescriptor AcceptNonBlock(StaticSocketAddress &address) const noexcept { + return UniqueSocketDescriptor(SocketDescriptor::AcceptNonBlock(address)); + } + +#ifndef _WIN32 + static bool CreateSocketPair(int domain, int type, int protocol, + UniqueSocketDescriptor &a, + UniqueSocketDescriptor &b) noexcept { + return SocketDescriptor::CreateSocketPair(domain, type, + protocol, + a, b); + } + + static bool CreateSocketPairNonBlock(int domain, int type, int protocol, + UniqueSocketDescriptor &a, + UniqueSocketDescriptor &b) noexcept { + return SocketDescriptor::CreateSocketPairNonBlock(domain, type, + protocol, + a, b); + } +#endif +}; diff --git a/src/system/EpollFD.cxx b/src/system/EpollFD.cxx index 6d9a5ea36f..a07c187d5a 100644 --- a/src/system/EpollFD.cxx +++ b/src/system/EpollFD.cxx @@ -5,7 +5,7 @@ #include "Error.hxx" EpollFD::EpollFD() - :fd(::epoll_create1(EPOLL_CLOEXEC)) + :fd(AdoptTag{}, ::epoll_create1(EPOLL_CLOEXEC)) { if (!fd.IsDefined()) throw MakeErrno("epoll_create1() failed"); diff --git a/src/system/EventFD.cxx b/src/system/EventFD.cxx index c567a141ed..838659d1ef 100644 --- a/src/system/EventFD.cxx +++ b/src/system/EventFD.cxx @@ -10,7 +10,7 @@ #include EventFD::EventFD() - :fd(::eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC)) + :fd(AdoptTag{}, ::eventfd(0, EFD_NONBLOCK|EFD_CLOEXEC)) { if (!fd.IsDefined()) throw MakeErrno("eventfd() failed"); diff --git a/src/system/SignalFD.cxx b/src/system/SignalFD.cxx index 72d1da05af..2394b30229 100644 --- a/src/system/SignalFD.cxx +++ b/src/system/SignalFD.cxx @@ -17,7 +17,7 @@ SignalFD::Create(const sigset_t &mask) throw MakeErrno("signalfd() failed"); if (!fd.IsDefined()) { - fd = UniqueFileDescriptor{new_fd}; + fd = UniqueFileDescriptor{AdoptTag{}, new_fd}; } assert(new_fd == fd.Get());