lshal: Add fqname to debug error messages

If any error comes up when invoking debug, write fqname and the error
message to the error output stream.

Test: manual. Add addPostCommandTask to a HAL that keeps writing to the
fd after debug() finishes. lshal debug terminates with fqname and
the error message `timeout reading from pipe, output may be truncated.`

Fixes: 169247570

Change-Id: Idf8944e3cde08dc86766b144c4a3037cbcf6b3dc
This commit is contained in:
Yifan Hong 2020-09-24 11:50:50 -07:00
parent 52e3b47cae
commit 8a662475ef
3 changed files with 31 additions and 13 deletions

View file

@ -141,7 +141,7 @@ Status Lshal::emitDebugInfo(
}
}
PipeRelay relay(out);
PipeRelay relay(out, err, interfaceName, instanceName);
if (relay.initCheck() != OK) {
std::string msg = "PipeRelay::initCheck() FAILED w/ " + std::to_string(relay.initCheck());

View file

@ -23,7 +23,6 @@
#include <atomic>
#include <android-base/logging.h>
#include <utils/Thread.h>
namespace android {
@ -31,8 +30,15 @@ namespace lshal {
static constexpr struct timeval READ_TIMEOUT { .tv_sec = 1, .tv_usec = 0 };
static std::string getThreadName(std::string interfaceName, const std::string &instanceName) {
auto dot = interfaceName.rfind(".");
if (dot != std::string::npos) interfaceName = interfaceName.substr(dot + 1);
return "RelayThread_" + interfaceName + "_" + instanceName;
}
struct PipeRelay::RelayThread : public Thread {
explicit RelayThread(int fd, std::ostream &os);
explicit RelayThread(int fd, std::ostream &os, const NullableOStream<std::ostream> &err,
const std::string &fqName);
bool threadLoop() override;
void setFinished();
@ -40,6 +46,7 @@ struct PipeRelay::RelayThread : public Thread {
private:
int mFd;
std::ostream &mOutStream;
NullableOStream<std::ostream> mErrStream;
// 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
@ -47,13 +54,17 @@ private:
// read() are executed until data are drained.
std::atomic_bool mFinished;
std::string mFqName;
DISALLOW_COPY_AND_ASSIGN(RelayThread);
};
////////////////////////////////////////////////////////////////////////////////
PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os)
: mFd(fd), mOutStream(os), mFinished(false) {}
PipeRelay::RelayThread::RelayThread(int fd, std::ostream &os,
const NullableOStream<std::ostream> &err,
const std::string &fqName)
: mFd(fd), mOutStream(os), mErrStream(err), mFinished(false), mFqName(fqName) {}
bool PipeRelay::RelayThread::threadLoop() {
char buffer[1024];
@ -66,13 +77,14 @@ bool PipeRelay::RelayThread::threadLoop() {
int res = TEMP_FAILURE_RETRY(select(mFd + 1, &set, nullptr, nullptr, &timeout));
if (res < 0) {
PLOG(INFO) << "select() failed";
mErrStream << "debug " << mFqName << ": select() failed";
return false;
}
if (res == 0 || !FD_ISSET(mFd, &set)) {
if (mFinished) {
LOG(WARNING) << "debug: timeout reading from pipe, output may be truncated.";
mErrStream << "debug " << mFqName
<< ": timeout reading from pipe, output may be truncated.";
return false;
}
// timeout, but debug() has not returned, so wait for HAL to finish.
@ -83,7 +95,7 @@ bool PipeRelay::RelayThread::threadLoop() {
ssize_t n = TEMP_FAILURE_RETRY(read(mFd, buffer, sizeof(buffer)));
if (n < 0) {
PLOG(ERROR) << "read() failed";
mErrStream << "debug " << mFqName << ": read() failed";
}
if (n <= 0) {
@ -101,8 +113,9 @@ void PipeRelay::RelayThread::setFinished() {
////////////////////////////////////////////////////////////////////////////////
PipeRelay::PipeRelay(std::ostream &os)
: mInitCheck(NO_INIT) {
PipeRelay::PipeRelay(std::ostream &os, const NullableOStream<std::ostream> &err,
const std::string &interfaceName, const std::string &instanceName)
: mInitCheck(NO_INIT) {
int res = pipe(mFds);
if (res < 0) {
@ -110,8 +123,8 @@ PipeRelay::PipeRelay(std::ostream &os)
return;
}
mThread = new RelayThread(mFds[0], os);
mInitCheck = mThread->run("RelayThread");
mThread = new RelayThread(mFds[0], os, err, interfaceName + "/" + instanceName);
mInitCheck = mThread->run(getThreadName(interfaceName, instanceName).c_str());
}
void PipeRelay::CloseFd(int *fd) {

View file

@ -21,6 +21,8 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
#include "NullableOStream.h"
namespace android {
namespace lshal {
@ -28,7 +30,10 @@ namespace lshal {
* written to the "write"-end of the pair to the specified output stream "os".
*/
struct PipeRelay {
explicit PipeRelay(std::ostream &os);
explicit PipeRelay(std::ostream& os,
const NullableOStream<std::ostream>& err,
const std::string& interfaceName,
const std::string& instanceName);
~PipeRelay();
status_t initCheck() const;