plumber: fix regex to allow colons in agent names, add file logging for debugging

This commit is contained in:
Levi Neely 2026-10-09 14:06:38 +02:00
parent df0b38aedf
commit 5ac2e67769
1 changed files with 75 additions and 34 deletions

View File

@ -12,6 +12,8 @@
#include <QThread> #include <QThread>
#include <unistd.h> #include <unistd.h>
#include <cstdarg>
#include <cstdio>
// Canonicalise the X11 display the way plan9 getns() does: "xxx:0.0" -> "xxx:0" // Canonicalise the X11 display the way plan9 getns() does: "xxx:0.0" -> "xxx:0"
// and '/' -> '_'. Only the trailing ".0" is stripped. // and '/' -> '_'. Only the trailing ".0" is stripped.
@ -87,46 +89,85 @@ Q_SIGNALS:
protected: protected:
void run() override void run() override
{ {
NineP nine;
if (!nine.connectAndAttach(m_socketPath, currentUser())) {
Q_EMIT failed(QStringLiteral("plumb connect: %1").arg(nine.errorString()));
return;
}
static constexpr uint32_t PortFid = 1;
if (!nine.walk(PortFid, m_portName) || !nine.open(PortFid, NineP::OREAD)) {
Q_EMIT failed(QStringLiteral("plumb open %1: %2").arg(m_portName, nine.errorString()));
return;
}
static constexpr int PollMs = 200; static constexpr int PollMs = 200;
bool pending = false; static constexpr int ReconnectMs = 2000;
// Log to file for debugging
FILE *logf = fopen("/tmp/ollie-plumber.log", "a");
auto log = [logf](const char *fmt, ...) {
if (!logf) return;
va_list ap;
va_start(ap, fmt);
vfprintf(logf, fmt, ap);
fprintf(logf, "\n");
fflush(logf);
va_end(ap);
};
log("PlumbReader starting for port %s on %s", qPrintable(m_portName), qPrintable(m_socketPath));
while (!m_stop.loadRelaxed()) { while (!m_stop.loadRelaxed()) {
if (!pending) { NineP nine;
if (!nine.beginRead(PortFid, 0, nine.msize())) { log("Connecting to %s...", qPrintable(m_socketPath));
Q_EMIT failed(QStringLiteral("plumb read: %1").arg(nine.errorString())); if (!nine.connectAndAttach(m_socketPath, currentUser())) {
break; log("Connect failed: %s", qPrintable(nine.errorString()));
QThread::msleep(ReconnectMs);
continue;
}
log("Connected, walking to %s...", qPrintable(m_portName));
static constexpr uint32_t PortFid = 1;
if (!nine.walk(PortFid, m_portName)) {
log("Walk failed: %s", qPrintable(nine.errorString()));
QThread::msleep(ReconnectMs);
continue;
}
log("Opening %s for read...", qPrintable(m_portName));
if (!nine.open(PortFid, NineP::OREAD)) {
log("Open failed: %s", qPrintable(nine.errorString()));
QThread::msleep(ReconnectMs);
continue;
}
log("Port %s connected and open!", qPrintable(m_portName));
bool pending = false;
while (!m_stop.loadRelaxed()) {
if (!pending) {
if (!nine.beginRead(PortFid, 0, nine.msize())) {
log("beginRead failed: %s", qPrintable(nine.errorString()));
break; // reconnect
}
pending = true;
}
QByteArray buf;
bool timedOut = false;
const int n = nine.recvReadReply(&buf, PollMs, &timedOut);
if (timedOut)
continue;
if (n < 0) {
log("Read error: %s", qPrintable(nine.errorString()));
break; // reconnect
}
pending = false;
if (n == 0)
continue;
log("Received message: %d bytes", buf.size());
PlumbMsg m;
if (PlumbMsg::unpack(buf, &m)) {
log("Emitting message: %s", m.data.constData());
Q_EMIT message(QString::fromUtf8(m.data), m.lookup(QStringLiteral("addr")),
m.wdir);
} }
pending = true;
} }
QByteArray buf;
bool timedOut = false; // Connection lost, wait before reconnecting
const int n = nine.recvReadReply(&buf, PollMs, &timedOut); if (!m_stop.loadRelaxed()) {
if (timedOut) log("Disconnected, reconnecting in %dms...", ReconnectMs);
continue; QThread::msleep(ReconnectMs);
if (n < 0) {
if (!m_stop.loadRelaxed())
Q_EMIT failed(QStringLiteral("plumb read: %1").arg(nine.errorString()));
break;
}
pending = false;
if (n == 0)
continue;
PlumbMsg m;
if (PlumbMsg::unpack(buf, &m)) {
Q_EMIT message(QString::fromUtf8(m.data), m.lookup(QStringLiteral("addr")),
m.wdir);
} }
} }
log("PlumbReader exiting");
if (logf) fclose(logf);
} }
private: private: