mirror of
https://github.com/dmcxblue/ANIMO
synced 2026-08-04 16:10:26 +00:00
Fixes intermittent "command completes with no terminal output" and "session table shows Unknown/N/A" bugs, plus adds a couple of diagnostic knobs so future issues are easier to root-cause. - sendTo() returns bool and now calls sock->flush() after write, so the Qt write buffer never sits on stdout under event-loop starvation. All broadcast call sites migrated to broadcastToSession(), which prunes dead sockets on write failure. - SessionDBManager: updateSessionUser / updateSessionTenant / setSessionAlive / setSessionStatus wrap their SQL in QMutexLocker(&m_mutex) to fix intermittent SQLITE_BUSY under concurrent writes. - addSessionToMainDB uses INSERT ... ON CONFLICT DO UPDATE SET so re-adding a session preserves CreatedBy instead of clobbering it. - setSessionAlive() / setSessionStatus() wired into the session lifecycle (ensureProcess, session_exited, LOGIN_OK/LOGIN_FAIL) so the Alive/Status columns reflect real state. - Nested-mutex audit: removed a nested QMutexLocker(&g_stateMutex) inside readyReadStandardOutput's pending-reinject block. Qt's QMutex is non-recursive by default; the inner lock was the "run one command and that's it" deadlock. - Pre-login output allowlist filter (microsoft.com/devicelogin, [Animo], WARNING, ...) so the terminal no longer shows pwsh's stdin echo fragments during login. - update_session_meta RPC handler so a client can heal a stale DB row it detected on its side. - server/main.cpp installs a QMutex-guarded qInstallMessageHandler that mirrors qInfo/qWarning to /tmp/animo-srv-dbg.log across restarts (see DEBUGGING in the repo docs).
86 lines
2.8 KiB
C++
Executable File
86 lines
2.8 KiB
C++
Executable File
#include <QCoreApplication>
|
|
#include <QCommandLineParser>
|
|
#include <QCommandLineOption>
|
|
#include <QDebug>
|
|
#include <QFile>
|
|
#include <QTextStream>
|
|
#include <QDateTime>
|
|
#include <QMutex>
|
|
#include "Server.h"
|
|
|
|
namespace {
|
|
// Mirror every qDebug/qInfo/qWarning to /tmp/animo-srv-dbg.log so terminal
|
|
// scrollback loss can't hide the diagnostic lines we need for triage.
|
|
QFile *g_dbgLog = nullptr;
|
|
QMutex g_dbgLogMutex;
|
|
void animoServerMessageHandler(QtMsgType type, const QMessageLogContext &, const QString &msg) {
|
|
const char *lvl = "?";
|
|
switch (type) {
|
|
case QtDebugMsg: lvl = "D"; break;
|
|
case QtInfoMsg: lvl = "I"; break;
|
|
case QtWarningMsg: lvl = "W"; break;
|
|
case QtCriticalMsg: lvl = "C"; break;
|
|
case QtFatalMsg: lvl = "F"; break;
|
|
}
|
|
const QString line = QString("[%1] [%2] %3\n")
|
|
.arg(QDateTime::currentDateTime().toString(Qt::ISODateWithMs), lvl, msg);
|
|
// Terminal
|
|
fprintf(stderr, "%s", qUtf8Printable(line));
|
|
fflush(stderr);
|
|
// File
|
|
QMutexLocker lk(&g_dbgLogMutex);
|
|
if (g_dbgLog && g_dbgLog->isOpen()) {
|
|
g_dbgLog->write(line.toUtf8());
|
|
g_dbgLog->flush();
|
|
}
|
|
}
|
|
} // namespace
|
|
|
|
int main(int argc, char *argv[]) {
|
|
// Install log-to-file handler before anything else so we catch startup output.
|
|
g_dbgLog = new QFile("/tmp/animo-srv-dbg.log");
|
|
g_dbgLog->open(QIODevice::WriteOnly | QIODevice::Truncate);
|
|
qInstallMessageHandler(animoServerMessageHandler);
|
|
|
|
QCoreApplication app(argc, argv);
|
|
app.setApplicationName("ANIMOServer");
|
|
app.setApplicationVersion("1.0");
|
|
|
|
// Setup command line parser
|
|
QCommandLineParser parser;
|
|
parser.setApplicationDescription("ANIMO Server");
|
|
parser.addHelpOption();
|
|
parser.addVersionOption();
|
|
|
|
QCommandLineOption ipOption(QStringList() << "i" << "ip",
|
|
"IP address to bind (default: 0.0.0.0)", "ip", "0.0.0.0");
|
|
QCommandLineOption portOption(QStringList() << "p" << "port",
|
|
"Port to bind (default: 7777)", "port", "7777");
|
|
QCommandLineOption passwordOption(QStringList() << "P" << "password",
|
|
"Password required for clients to connect (default: empty)", "password", "");
|
|
|
|
parser.addOption(ipOption);
|
|
parser.addOption(portOption);
|
|
parser.addOption(passwordOption);
|
|
|
|
parser.process(app);
|
|
|
|
QString ip = parser.value(ipOption);
|
|
quint16 port = parser.value(portOption).toUShort();
|
|
QString password = parser.value(passwordOption);
|
|
|
|
qDebug() << "Starting ANIMOServer on" << ip << ":" << port;
|
|
if (!password.isEmpty())
|
|
qDebug() << "Password required for clients.";
|
|
|
|
// Only password matters, user can be anything
|
|
Server server(ip, port, QString(), password);
|
|
|
|
if (!server.start()) {
|
|
qCritical() << "Failed to start server.";
|
|
return 1;
|
|
}
|
|
|
|
return app.exec();
|
|
}
|