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:
parent
52e3b47cae
commit
8a662475ef
3 changed files with 31 additions and 13 deletions
|
@ -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());
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue