adb: fix fd double close, Subprocess lifetime issue.
am: 69d2f98197
Change-Id: I7797d5dee022bfdd6f165221340095f7836eea99
This commit is contained in:
commit
9150b1288e
20 changed files with 124 additions and 81 deletions
|
@ -20,6 +20,7 @@
|
|||
#include <string>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
void close_stdin();
|
||||
|
||||
|
@ -50,6 +51,14 @@ bool set_file_block_mode(int fd, bool block);
|
|||
extern int adb_close(int fd);
|
||||
|
||||
// Helper to automatically close an FD when it goes out of scope.
|
||||
struct AdbCloser {
|
||||
static void Close(int fd) {
|
||||
adb_close(fd);
|
||||
}
|
||||
};
|
||||
|
||||
using unique_fd = android::base::unique_fd_impl<AdbCloser>;
|
||||
|
||||
class ScopedFd {
|
||||
public:
|
||||
ScopedFd() {
|
||||
|
|
|
@ -160,9 +160,14 @@ class Subprocess {
|
|||
pid_t pid() const { return pid_; }
|
||||
|
||||
// Sets up FDs, forks a subprocess, starts the subprocess manager thread,
|
||||
// and exec's the child. Returns false on failure.
|
||||
// and exec's the child. Returns false and sets error on failure.
|
||||
bool ForkAndExec(std::string* _Nonnull error);
|
||||
|
||||
// Start the subprocess manager thread. Consumes the subprocess, regardless of success.
|
||||
// Returns false and sets error on failure.
|
||||
static bool StartThread(std::unique_ptr<Subprocess> subprocess,
|
||||
std::string* _Nonnull error);
|
||||
|
||||
private:
|
||||
// Opens the file at |pts_name|.
|
||||
int OpenPtyChildFd(const char* pts_name, ScopedFd* error_sfd);
|
||||
|
@ -391,14 +396,19 @@ bool Subprocess::ForkAndExec(std::string* error) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!adb_thread_create(ThreadHandler, this)) {
|
||||
D("subprocess parent: completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Subprocess::StartThread(std::unique_ptr<Subprocess> subprocess, std::string* error) {
|
||||
Subprocess* raw = subprocess.release();
|
||||
if (!adb_thread_create(ThreadHandler, raw)) {
|
||||
*error =
|
||||
android::base::StringPrintf("failed to create subprocess thread: %s", strerror(errno));
|
||||
kill(pid_, SIGKILL);
|
||||
kill(raw->pid_, SIGKILL);
|
||||
return false;
|
||||
}
|
||||
|
||||
D("subprocess parent: completed");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -442,6 +452,7 @@ void Subprocess::ThreadHandler(void* userdata) {
|
|||
adb_thread_setname(android::base::StringPrintf(
|
||||
"shell srvc %d", subprocess->local_socket_fd()));
|
||||
|
||||
D("passing data streams for PID %d", subprocess->pid());
|
||||
subprocess->PassDataStreams();
|
||||
|
||||
D("deleting Subprocess for PID %d", subprocess->pid());
|
||||
|
@ -738,7 +749,7 @@ int StartSubprocess(const char* name, const char* terminal_type,
|
|||
protocol == SubprocessProtocol::kNone ? "none" : "shell",
|
||||
terminal_type, name);
|
||||
|
||||
Subprocess* subprocess = new Subprocess(name, terminal_type, type, protocol);
|
||||
auto subprocess = std::make_unique<Subprocess>(name, terminal_type, type, protocol);
|
||||
if (!subprocess) {
|
||||
LOG(ERROR) << "failed to allocate new subprocess";
|
||||
return ReportError(protocol, "failed to allocate new subprocess");
|
||||
|
@ -747,11 +758,17 @@ int StartSubprocess(const char* name, const char* terminal_type,
|
|||
std::string error;
|
||||
if (!subprocess->ForkAndExec(&error)) {
|
||||
LOG(ERROR) << "failed to start subprocess: " << error;
|
||||
delete subprocess;
|
||||
return ReportError(protocol, error);
|
||||
}
|
||||
|
||||
D("subprocess creation successful: local_socket_fd=%d, pid=%d",
|
||||
subprocess->local_socket_fd(), subprocess->pid());
|
||||
return subprocess->local_socket_fd();
|
||||
unique_fd local_socket(dup(subprocess->local_socket_fd()));
|
||||
D("subprocess creation successful: local_socket_fd=%d, pid=%d", local_socket.get(),
|
||||
subprocess->pid());
|
||||
|
||||
if (!Subprocess::StartThread(std::move(subprocess), &error)) {
|
||||
LOG(ERROR) << "failed to start subprocess management thread: " << error;
|
||||
return ReportError(protocol, error);
|
||||
}
|
||||
|
||||
return local_socket.release();
|
||||
}
|
||||
|
|
|
@ -29,8 +29,9 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// Include this before open/unlink are defined as macros below.
|
||||
// Include this before open/close/unlink are defined as macros below.
|
||||
#include <android-base/errors.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <android-base/utf8.h>
|
||||
|
||||
/*
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
// special handling to get the error string. Refer to Microsoft documentation
|
||||
// to determine which error code to check for each function.
|
||||
|
||||
#ifndef BASE_ERRORS_H
|
||||
#define BASE_ERRORS_H
|
||||
#ifndef ANDROID_BASE_ERRORS_H
|
||||
#define ANDROID_BASE_ERRORS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -43,4 +43,4 @@ std::string SystemErrorCodeToString(int error_code);
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_ERRORS_H
|
||||
#endif // ANDROID_BASE_ERRORS_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_FILE_H
|
||||
#define BASE_FILE_H
|
||||
#ifndef ANDROID_BASE_FILE_H
|
||||
#define ANDROID_BASE_FILE_H
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <string>
|
||||
|
@ -46,4 +46,4 @@ bool RemoveFileIfExists(const std::string& path, std::string* err = nullptr);
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_FILE_H
|
||||
#endif // ANDROID_BASE_FILE_H
|
||||
|
|
|
@ -13,8 +13,9 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef BASE_LOGGING_H
|
||||
#define BASE_LOGGING_H
|
||||
|
||||
#ifndef ANDROID_BASE_LOGGING_H
|
||||
#define ANDROID_BASE_LOGGING_H
|
||||
|
||||
// NOTE: For Windows, you must include logging.h after windows.h to allow the
|
||||
// following code to suppress the evil ERROR macro:
|
||||
|
@ -334,4 +335,4 @@ class ScopedLogSeverity {
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_LOGGING_H
|
||||
#endif // ANDROID_BASE_LOGGING_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_MACROS_H
|
||||
#define UTILS_MACROS_H
|
||||
#ifndef ANDROID_BASE_MACROS_H
|
||||
#define ANDROID_BASE_MACROS_H
|
||||
|
||||
#include <stddef.h> // for size_t
|
||||
#include <unistd.h> // for TEMP_FAILURE_RETRY
|
||||
|
@ -185,4 +185,4 @@ void UNUSED(const T&...) {
|
|||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif // UTILS_MACROS_H
|
||||
#endif // ANDROID_BASE_MACROS_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_MEMORY_H
|
||||
#define BASE_MEMORY_H
|
||||
#ifndef ANDROID_BASE_MEMORY_H
|
||||
#define ANDROID_BASE_MEMORY_H
|
||||
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
@ -44,4 +44,4 @@ static inline void put_unaligned(T* address, T v) {
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_MEMORY_H
|
||||
#endif // ANDROID_BASE_MEMORY_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_PARSEINT_H
|
||||
#define BASE_PARSEINT_H
|
||||
#ifndef ANDROID_BASE_PARSEINT_H
|
||||
#define ANDROID_BASE_PARSEINT_H
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -70,4 +70,4 @@ bool ParseInt(const char* s, T* out,
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_PARSEINT_H
|
||||
#endif // ANDROID_BASE_PARSEINT_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_PARSENETADDRESS_H
|
||||
#define BASE_PARSENETADDRESS_H
|
||||
#ifndef ANDROID_BASE_PARSENETADDRESS_H
|
||||
#define ANDROID_BASE_PARSENETADDRESS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -35,4 +35,4 @@ bool ParseNetAddress(const std::string& address, std::string* host, int* port,
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_PARSENETADDRESS_H
|
||||
#endif // ANDROID_BASE_PARSENETADDRESS_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STRINGPRINTF_H
|
||||
#define BASE_STRINGPRINTF_H
|
||||
#ifndef ANDROID_BASE_STRINGPRINTF_H
|
||||
#define ANDROID_BASE_STRINGPRINTF_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string>
|
||||
|
@ -53,4 +53,4 @@ void StringAppendV(std::string* dst, const char* format, va_list ap)
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_STRINGPRINTF_H
|
||||
#endif // ANDROID_BASE_STRINGPRINTF_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_STRINGS_H
|
||||
#define BASE_STRINGS_H
|
||||
#ifndef ANDROID_BASE_STRINGS_H
|
||||
#define ANDROID_BASE_STRINGS_H
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
@ -65,4 +65,4 @@ bool EndsWith(const std::string& s, const char* suffix);
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_STRINGS_H
|
||||
#endif // ANDROID_BASE_STRINGS_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TEST_UTILS_H
|
||||
#define TEST_UTILS_H
|
||||
#ifndef ANDROID_BASE_TEST_UTILS_H
|
||||
#define ANDROID_BASE_TEST_UTILS_H
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -48,4 +48,4 @@ class TemporaryDir {
|
|||
DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
|
||||
};
|
||||
|
||||
#endif // TEST_UTILS_H
|
||||
#endif // ANDROID_BASE_TEST_UTILS_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_THREAD_ANNOTATIONS_H
|
||||
#define UTILS_THREAD_ANNOTATIONS_H
|
||||
#ifndef ANDROID_BASE_THREAD_ANNOTATIONS_H
|
||||
#define ANDROID_BASE_THREAD_ANNOTATIONS_H
|
||||
|
||||
#if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
|
||||
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
|
||||
|
@ -80,4 +80,4 @@
|
|||
#define NO_THREAD_SAFETY_ANALYSIS \
|
||||
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
|
||||
|
||||
#endif // UTILS_THREAD_ANNOTATIONS_H
|
||||
#endif // ANDROID_BASE_THREAD_ANNOTATIONS_H
|
||||
|
|
|
@ -19,39 +19,54 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
// DO NOT INCLUDE OTHER LIBBASE HEADERS!
|
||||
// This file gets used in libbinder, and libbinder is used everywhere.
|
||||
// Including other headers from libbase frequently results in inclusion of
|
||||
// android-base/macros.h, which causes macro collisions.
|
||||
|
||||
/* Container for a file descriptor that automatically closes the descriptor as
|
||||
* it goes out of scope.
|
||||
*
|
||||
* unique_fd ufd(open("/some/path", "r"));
|
||||
*
|
||||
* if (ufd.get() < 0) // invalid descriptor
|
||||
* return error;
|
||||
*
|
||||
* // Do something useful
|
||||
*
|
||||
* return 0; // descriptor is closed here
|
||||
*/
|
||||
// Container for a file descriptor that automatically closes the descriptor as
|
||||
// it goes out of scope.
|
||||
//
|
||||
// unique_fd ufd(open("/some/path", "r"));
|
||||
// if (ufd.get() == -1) return error;
|
||||
//
|
||||
// // Do something useful, possibly including 'return'.
|
||||
//
|
||||
// return 0; // Descriptor is closed for you.
|
||||
//
|
||||
// unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help
|
||||
// you find this class if you're searching for one of those names.
|
||||
namespace android {
|
||||
namespace base {
|
||||
|
||||
class unique_fd final {
|
||||
struct DefaultCloser {
|
||||
static void Close(int fd) {
|
||||
// Even if close(2) fails with EINTR, the fd will have been closed.
|
||||
// Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone
|
||||
// else's fd.
|
||||
// http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html
|
||||
::close(fd);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Closer>
|
||||
class unique_fd_impl final {
|
||||
public:
|
||||
unique_fd() : value_(-1) {}
|
||||
unique_fd_impl() : value_(-1) {}
|
||||
|
||||
explicit unique_fd(int value) : value_(value) {}
|
||||
~unique_fd() { clear(); }
|
||||
explicit unique_fd_impl(int value) : value_(value) {}
|
||||
~unique_fd_impl() { clear(); }
|
||||
|
||||
unique_fd(unique_fd&& other) : value_(other.release()) {}
|
||||
unique_fd& operator = (unique_fd&& s) {
|
||||
unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {}
|
||||
unique_fd_impl& operator=(unique_fd_impl&& s) {
|
||||
reset(s.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
void reset(int new_value) {
|
||||
if (value_ >= 0)
|
||||
close(value_);
|
||||
if (value_ != -1) {
|
||||
Closer::Close(value_);
|
||||
}
|
||||
value_ = new_value;
|
||||
}
|
||||
|
||||
|
@ -60,8 +75,9 @@ class unique_fd final {
|
|||
}
|
||||
|
||||
int get() const { return value_; }
|
||||
operator int() const { return get(); }
|
||||
|
||||
int release() {
|
||||
int release() __attribute__((warn_unused_result)) {
|
||||
int ret = value_;
|
||||
value_ = -1;
|
||||
return ret;
|
||||
|
@ -70,10 +86,13 @@ class unique_fd final {
|
|||
private:
|
||||
int value_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(unique_fd);
|
||||
unique_fd_impl(const unique_fd_impl&);
|
||||
void operator=(const unique_fd_impl&);
|
||||
};
|
||||
|
||||
using unique_fd = unique_fd_impl<DefaultCloser>;
|
||||
|
||||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // ANDROID_BASE_UNIQUE_FD_H
|
||||
#endif // ANDROID_BASE_UNIQUE_FD_H
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef BASE_UTF8_H
|
||||
#define BASE_UTF8_H
|
||||
#ifndef ANDROID_BASE_UTF8_H
|
||||
#define ANDROID_BASE_UTF8_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <string>
|
||||
|
@ -84,4 +84,4 @@ using ::unlink;
|
|||
} // namespace base
|
||||
} // namespace android
|
||||
|
||||
#endif // BASE_UTF8_H
|
||||
#endif // ANDROID_BASE_UTF8_H
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace {
|
|||
// the value of the record.
|
||||
bool CreateEmptyBootEventRecord(const std::string& record_path, int32_t value) {
|
||||
android::base::unique_fd record_fd(creat(record_path.c_str(), S_IRUSR | S_IWUSR));
|
||||
if (record_fd.get() == -1) {
|
||||
if (record_fd == -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ bool CreateEmptyBootEventRecord(const std::string& record_path, int32_t value) {
|
|||
// ensure the validity of the file mtime value, i.e., to check that the record
|
||||
// file mtime values are not changed once set.
|
||||
// TODO(jhawkins): Remove this block.
|
||||
if (!android::base::WriteStringToFd(std::to_string(value), record_fd.get())) {
|
||||
if (!android::base::WriteStringToFd(std::to_string(value), record_fd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,11 +30,10 @@
|
|||
bool ProcessMappings(pid_t pid, allocator::vector<Mapping>& mappings) {
|
||||
char map_buffer[1024];
|
||||
snprintf(map_buffer, sizeof(map_buffer), "/proc/%d/maps", pid);
|
||||
int fd = open(map_buffer, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
android::base::unique_fd fd(open(map_buffer, O_RDONLY));
|
||||
if (fd == -1) {
|
||||
return false;
|
||||
}
|
||||
android::base::unique_fd fd_guard{fd};
|
||||
|
||||
LineBuffer line_buf(fd, map_buffer, sizeof(map_buffer));
|
||||
char* line;
|
||||
|
|
|
@ -108,12 +108,11 @@ bool ThreadCaptureImpl::ListThreads(TidList& tids) {
|
|||
strlcat(path, pid_str, sizeof(path));
|
||||
strlcat(path, "/task", sizeof(path));
|
||||
|
||||
int fd = open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
|
||||
if (fd < 0) {
|
||||
android::base::unique_fd fd(open(path, O_CLOEXEC | O_DIRECTORY | O_RDONLY));
|
||||
if (fd == -1) {
|
||||
ALOGE("failed to open %s: %s", path, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
android::base::unique_fd fd_guard{fd};
|
||||
|
||||
struct linux_dirent64 {
|
||||
uint64_t d_ino;
|
||||
|
@ -125,7 +124,7 @@ bool ThreadCaptureImpl::ListThreads(TidList& tids) {
|
|||
char dirent_buf[4096];
|
||||
ssize_t nread;
|
||||
do {
|
||||
nread = syscall(SYS_getdents64, fd, dirent_buf, sizeof(dirent_buf));
|
||||
nread = syscall(SYS_getdents64, fd.get(), dirent_buf, sizeof(dirent_buf));
|
||||
if (nread < 0) {
|
||||
ALOGE("failed to get directory entries from %s: %s", path, strerror(errno));
|
||||
return false;
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
#include "Allocator.h"
|
||||
#include "ScopedDisableMalloc.h"
|
||||
#include "ScopedPipe.h"
|
||||
|
|
Loading…
Reference in a new issue