summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'base/include/android-base/unique_fd.h')
-rw-r--r--base/include/android-base/unique_fd.h82
1 files changed, 14 insertions, 68 deletions
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 019d337c4..c7330817a 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -42,29 +42,10 @@
42// 42//
43// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help 43// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
44// you find this class if you're searching for one of those names. 44// you find this class if you're searching for one of those names.
45
46#if defined(__BIONIC__)
47#include <android/fdsan.h>
48#endif
49
50namespace android { 45namespace android {
51namespace base { 46namespace base {
52 47
53struct DefaultCloser { 48struct DefaultCloser {
54#if defined(__BIONIC__)
55 static void Tag(int fd, void* old_addr, void* new_addr) {
56 uint64_t old_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
57 reinterpret_cast<uint64_t>(old_addr));
58 uint64_t new_tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
59 reinterpret_cast<uint64_t>(new_addr));
60 android_fdsan_exchange_owner_tag(fd, old_tag, new_tag);
61 }
62 static void Close(int fd, void* addr) {
63 uint64_t tag = android_fdsan_create_owner_tag(ANDROID_FDSAN_OWNER_TYPE_UNIQUE_FD,
64 reinterpret_cast<uint64_t>(addr));
65 android_fdsan_close_with_tag(fd, tag);
66 }
67#else
68 static void Close(int fd) { 49 static void Close(int fd) {
69 // Even if close(2) fails with EINTR, the fd will have been closed. 50 // Even if close(2) fails with EINTR, the fd will have been closed.
70 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone 51 // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
@@ -72,75 +53,40 @@ struct DefaultCloser {
72 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html 53 // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
73 ::close(fd); 54 ::close(fd);
74 } 55 }
75#endif
76}; 56};
77 57
78template <typename Closer> 58template <typename Closer>
79class unique_fd_impl final { 59class unique_fd_impl final {
80 public: 60 public:
81 unique_fd_impl() {} 61 unique_fd_impl() : value_(-1) {}
82 62
83 explicit unique_fd_impl(int fd) { reset(fd); } 63 explicit unique_fd_impl(int value) : value_(value) {}
84 ~unique_fd_impl() { reset(); } 64 ~unique_fd_impl() { reset(); }
85 65
86 unique_fd_impl(unique_fd_impl&& other) { reset(other.release()); } 66 unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
87 unique_fd_impl& operator=(unique_fd_impl&& s) { 67 unique_fd_impl& operator=(unique_fd_impl&& s) {
88 int fd = s.fd_; 68 reset(s.release());
89 s.fd_ = -1;
90 reset(fd, &s);
91 return *this; 69 return *this;
92 } 70 }
93 71
94 void reset(int new_value = -1) { reset(new_value, nullptr); } 72 void reset(int new_value = -1) {
73 if (value_ != -1) {
74 Closer::Close(value_);
75 }
76 value_ = new_value;
77 }
95 78
96 int get() const { return fd_; } 79 int get() const { return value_; }
97 operator int() const { return get(); } 80 operator int() const { return get(); }
98 81
99 int release() __attribute__((warn_unused_result)) { 82 int release() __attribute__((warn_unused_result)) {
100 tag(fd_, this, nullptr); 83 int ret = value_;
101 int ret = fd_; 84 value_ = -1;
102 fd_ = -1;
103 return ret; 85 return ret;
104 } 86 }
105 87
106 private: 88 private:
107 void reset(int new_value, void* previous_tag) { 89 int value_;
108 if (fd_ != -1) {
109 close(fd_, this);
110 }
111
112 fd_ = new_value;
113 if (new_value != -1) {
114 tag(new_value, previous_tag, this);
115 }
116 }
117
118 int fd_ = -1;
119
120 // Template magic to use Closer::Tag if available, and do nothing if not.
121 // If Closer::Tag exists, this implementation is preferred, because int is a better match.
122 // If not, this implementation is SFINAEd away, and the no-op below is the only one that exists.
123 template <typename T = Closer>
124 static auto tag(int fd, void* old_tag, void* new_tag)
125 -> decltype(T::Tag(fd, old_tag, new_tag), void()) {
126 T::Tag(fd, old_tag, new_tag);
127 }
128
129 template <typename T = Closer>
130 static void tag(long, void*, void*) {
131 // No-op.
132 }
133
134 // Same as above, to select between Closer::Close(int) and Closer::Close(int, void*).
135 template <typename T = Closer>
136 static auto close(int fd, void* tag_value) -> decltype(T::Close(fd, tag_value), void()) {
137 T::Close(fd, tag_value);
138 }
139
140 template <typename T = Closer>
141 static auto close(int fd, void*) -> decltype(T::Close(fd), void()) {
142 T::Close(fd);
143 }
144 90
145 unique_fd_impl(const unique_fd_impl&); 91 unique_fd_impl(const unique_fd_impl&);
146 void operator=(const unique_fd_impl&); 92 void operator=(const unique_fd_impl&);