drm_hwcomposer: Rework autofd
Motivation: Current implementation of UniqueFd can be used in a different ways, making analytical tracking of FD lifecycle much harder than it may be. Keep this part clean is very important, since any wrong code may open a hard-to-detect runtime bugs and fd leaks, which may accidentally slip into the production. Implementation: 1. Combine UniqueFd anf OutputFd into single class. 2. Reduce the API to be minimal and sufficient. 3. Document the API and use cases. 4. Move to utils/UniqueFd.h. 5. dup(fd) was replaced with fcntl(fd, F_DUPFD_CLOEXEC)) to address clang-tidy findings. Find more information at [1] [1]: https://clang.llvm.org/extra/clang-tidy/checks/android-cloexec-dup.html Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
This commit is contained in:
parent
5128715b42
commit
0fade37afd
13 changed files with 156 additions and 178 deletions
111
utils/UniqueFd.h
Normal file
111
utils/UniqueFd.h
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright (C) 2015, 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UNIQUEFD_H_
|
||||
#define UNIQUEFD_H_
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace android {
|
||||
|
||||
/*
|
||||
* Using UniqueFd:
|
||||
* 1. Create UniqueFd object:
|
||||
* auto fd_obj = UniqueFd(open("SomeFile", xxx));
|
||||
*
|
||||
* 2. Check whether the fd_obj is empty:
|
||||
* if (!fd_obj) { return -errno; }
|
||||
*
|
||||
* 3. Accessing the file descriptor:
|
||||
* int ret = read(fd_obj.Get(), buf, buf_size);
|
||||
*
|
||||
* 4. Closing the file:
|
||||
* FD will be closed once execution leaves fd_obj scope (on any return,
|
||||
* exception, destruction of class/struct where object is member, etc.).
|
||||
* User can also force closing the fd_obj by calling:
|
||||
* fd_obj = UniqueFd();
|
||||
* // fd is closed and fd_obj is empty now.
|
||||
*
|
||||
* 5. File descriptor may be transferred to the code, which will close it after
|
||||
* using. This can be done in 2 ways:
|
||||
* a. Duplicate the fd, in this case both fds should be closed separately:
|
||||
* int out_fd = dup(fd_obj.Get();
|
||||
* ...
|
||||
* close(out_fd);
|
||||
* b. Transfer ownership, use this method if you do not need the fd anymore.
|
||||
* int out_fd = fd_obj.Release();
|
||||
* // fd_obj is empty now.
|
||||
* ...
|
||||
* close(out_fd);
|
||||
*
|
||||
* 6. Transferring fd into another UniqueFD object:
|
||||
* UniqueFd fd_obj_2 = std::move(fd_obj);
|
||||
* // fd_obj empty now
|
||||
*/
|
||||
|
||||
constexpr int kEmptyFd = -1;
|
||||
|
||||
class UniqueFd {
|
||||
public:
|
||||
UniqueFd() = default;
|
||||
explicit UniqueFd(int fd) : fd_(fd){};
|
||||
|
||||
auto Release [[nodiscard]] () -> int {
|
||||
return std::exchange(fd_, kEmptyFd);
|
||||
}
|
||||
|
||||
auto Get [[nodiscard]] () const -> int {
|
||||
return fd_;
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return fd_ != kEmptyFd;
|
||||
}
|
||||
|
||||
~UniqueFd() {
|
||||
Set(kEmptyFd);
|
||||
}
|
||||
|
||||
/* Allow move semantics */
|
||||
UniqueFd(UniqueFd &&rhs) noexcept {
|
||||
Set(rhs.Release());
|
||||
}
|
||||
|
||||
auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & {
|
||||
Set(rhs.Release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Disable copy semantics */
|
||||
UniqueFd(const UniqueFd &) = delete;
|
||||
auto operator=(const UniqueFd &) = delete;
|
||||
|
||||
private:
|
||||
void Set(int new_fd) {
|
||||
if (fd_ != kEmptyFd) {
|
||||
close(fd_);
|
||||
}
|
||||
fd_ = new_fd;
|
||||
}
|
||||
|
||||
int fd_ = kEmptyFd;
|
||||
};
|
||||
|
||||
} // namespace android
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue