Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a662475 authored by Yifan Hong's avatar Yifan Hong
Browse files

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
parent 52e3b47c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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());
+24 −11
Original line number Diff line number Diff line
@@ -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,7 +113,8 @@ void PipeRelay::RelayThread::setFinished() {

////////////////////////////////////////////////////////////////////////////////

PipeRelay::PipeRelay(std::ostream &os)
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);

@@ -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) {
+6 −1
Original line number Diff line number Diff line
@@ -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;