summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yifan Hong <elsk@google.com> 2018-09-26 15:49:28 -0700
committer Yifan Hong <elsk@google.com> 2018-09-27 11:09:17 -0700
commitb1db390e2516e7b9fd388ae9f5a576ffcaf537c5 (patch)
treef2d4c28af3cd517cf37c1a8e270b12bb62a6ef3f
parenta5ae7868e74c70b7586b4cfe2f1e4311dbec3c05 (diff)
lshal: Allow read to timeout in debug()
Start timing when debug() has returned. When the specific timeout has reached (currently 1s) and the relay thread has not finish, tell the relay thread to stop. Test: while true; do date; lshal debug android.hardware.health.storage@1.0::IStorage/default; done Test: lshal_test Bug: 111997867 Change-Id: Ib9235d3bd2fc3a54eb316da8d8b59d987988b134
-rw-r--r--cmds/lshal/PipeRelay.cpp55
1 files changed, 51 insertions, 4 deletions
diff --git a/cmds/lshal/PipeRelay.cpp b/cmds/lshal/PipeRelay.cpp
index 87d75ac2d4..820679fbe2 100644
--- a/cmds/lshal/PipeRelay.cpp
+++ b/cmds/lshal/PipeRelay.cpp
@@ -16,33 +16,75 @@
#include "PipeRelay.h"
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <atomic>
+
+#include <android-base/logging.h>
#include <utils/Thread.h>
namespace android {
namespace lshal {
+static constexpr struct timeval READ_TIMEOUT { .tv_sec = 1, .tv_usec = 0 };
+
struct PipeRelay::RelayThread : public Thread {
explicit RelayThread(int fd, std::ostream &os);
bool threadLoop() override;
+ void setFinished();
private:
int mFd;
std::ostream &mOutStream;
+ // If we were to use requestExit() and exitPending() instead, threadLoop()
+ // may not run at all by the time ~PipeRelay is called (i.e. debug() has
+ // returned from HAL). By using our own flag, we ensure that select() and
+ // read() are executed until data are drained.
+ std::atomic_bool mFinished;
+
DISALLOW_COPY_AND_ASSIGN(RelayThread);
};
////////////////////////////////////////////////////////////////////////////////
PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
- : mFd(fd),
- mOutStream(os) {
-}
+ : mFd(fd), mOutStream(os), mFinished(false) {}
bool PipeRelay::RelayThread::threadLoop() {
char buffer[1024];
- ssize_t n = read(mFd, buffer, sizeof(buffer));
+
+ fd_set set;
+ FD_ZERO(&set);
+ FD_SET(mFd, &set);
+
+ struct timeval timeout = READ_TIMEOUT;
+
+ int res = TEMP_FAILURE_RETRY(select(mFd + 1, &set, nullptr, nullptr, &timeout));
+ if (res < 0) {
+ PLOG(INFO) << "select() failed";
+ return false;
+ }
+
+ if (res == 0 || !FD_ISSET(mFd, &set)) {
+ if (mFinished) {
+ LOG(WARNING) << "debug: timeout reading from pipe, output may be truncated.";
+ return false;
+ }
+ // timeout, but debug() has not returned, so wait for HAL to finish.
+ return true;
+ }
+
+ // FD_ISSET(mFd, &set) == true. Data available, start reading
+ ssize_t n = TEMP_FAILURE_RETRY(read(mFd, buffer, sizeof(buffer)));
+
+ if (n < 0) {
+ PLOG(ERROR) << "read() failed";
+ }
if (n <= 0) {
return false;
@@ -53,6 +95,10 @@ bool PipeRelay::RelayThread::threadLoop() {
return true;
}
+void PipeRelay::RelayThread::setFinished() {
+ mFinished = true;
+}
+
////////////////////////////////////////////////////////////////////////////////
PipeRelay::PipeRelay(std::ostream &os)
@@ -79,6 +125,7 @@ PipeRelay::~PipeRelay() {
CloseFd(&mFds[1]);
if (mThread != nullptr) {
+ mThread->setFinished();
mThread->join();
mThread.clear();
}