diff --git a/CHANGELOG.md b/CHANGELOG.md index 39f3e8c..595deeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ * Create console once per Seer session. Instead of constant create/destroy. * Fixed regression when ignoring files to be opened in the EditorManager. +* Fixed regression when order of message tabs not being preserved between + sessions. ## [2.5] - 2024-12-24 * Console now supports a subset of ANSI color codes. diff --git a/src/SeerConsoleWidget.cpp b/src/SeerConsoleWidget.cpp index 28dba2b..c759827 100644 --- a/src/SeerConsoleWidget.cpp +++ b/src/SeerConsoleWidget.cpp @@ -359,7 +359,7 @@ void SeerConsoleWidget::deleteConsole () { void SeerConsoleWidget::connectConsole () { if (isConsoleConnected()) { - qDebug() << "Console is already connected!"; + //qDebug() << "Console is already connected!"; return; } @@ -376,7 +376,7 @@ void SeerConsoleWidget::connectConsole () { void SeerConsoleWidget::disconnectConsole () { if (isConsoleConnected() == false) { - qDebug() << "Console is already disconnected!"; + //qDebug() << "Console is already disconnected!"; return; } diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index fa50a8b..e60e9fd 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -70,6 +70,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { _rememberManualCommandCount = 10; _currentFrame = -1; + setIsQuitting(false); setNewExecutableFlag(true); setupUi(this); @@ -141,6 +142,9 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { // Restore tab ordering. readLogsSettings(); + // Handle the app's 'quit' event, in case we want to do things before exiting. + QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &SeerGdbWidget::handleAboutToQuit); + // Connect things. QObject::connect(logsTabWidget->tabBar(), &QTabBar::tabMoved, this, &SeerGdbWidget::handleLogsTabMoved); QObject::connect(logsTabWidget->tabBar(), &QTabBar::currentChanged, this, &SeerGdbWidget::handleLogsTabChanged); @@ -363,6 +367,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { // Restore window settings. readSettings(); + } SeerGdbWidget::~SeerGdbWidget () { @@ -688,11 +693,22 @@ void SeerGdbWidget::addMessage (const QString& message, QMessageBox::Icon messag _messagesBrowserWidget->addMessage(message, messageType); } -void SeerGdbWidget::handleLogsTabMoved (int from, int to) { +void SeerGdbWidget::handleLogsTabMoved (int to, int from) { Q_UNUSED(from); Q_UNUSED(to); + // Keep track of console tab if it moved. + if (_consoleIndex == from) { + qDebug() << "Console tab index changed from" << from << "to" << to; + _consoleIndex = to; + } + + // Don't handle anything here if Seer is exiting. + if (isQuitting()) { + return; + } + writeLogsSettings(); } @@ -700,6 +716,11 @@ void SeerGdbWidget::handleLogsTabChanged (int index) { Q_UNUSED(index); + // Don't handle anything here if Seer is exiting. + if (isQuitting()) { + return; + } + writeLogsSettings(); } @@ -725,8 +746,8 @@ void SeerGdbWidget::writeLogsSettings () { QString current = logsTabWidget->tabBar()->tabText(logsTabWidget->tabBar()->currentIndex()); - qDebug() << "Tabs" << tabs; - qDebug() << "Current" << current; + //qDebug() << "Tabs" << tabs; + //qDebug() << "Current" << current; QSettings settings; @@ -774,6 +795,19 @@ void SeerGdbWidget::readLogsSettings () { } } + // Find the console tab index. + _consoleIndex = -1; + for (int i=0; itabBar()->count(); i++) { + if (logsTabWidget->tabBar()->tabText(i) == "Console output") { + _consoleIndex = i; + break; + } + } + + if (_consoleIndex < 0) { + qDebug() << "The console tab index is not in the settings."; + } + // Make a tab current. if (current != "") { for (int i=0; itabBar()->count(); i++) { @@ -1085,9 +1119,10 @@ void SeerGdbWidget::handleGdbAttachExecutable () { handleGdbSourceScripts(); } - // No console for 'attach' mode. + // No console for 'attach' mode but make sure it's reattached. setExecutableLaunchMode("attach"); setGdbRecordMode(""); + reattachConsole(); // Load ithe executable, if needed. if (newExecutableFlag() == true) { @@ -1158,10 +1193,11 @@ void SeerGdbWidget::handleGdbConnectExecutable () { handleGdbSourceScripts(); } - // No console for 'connect' mode. + // No console for 'connect' mode but make sure it's reattached. setExecutableLaunchMode("connect"); setGdbRecordMode(""); setExecutablePid(0); + reattachConsole(); // Connect to the remote gdbserver. handleGdbCommand(QString("-target-select extended-remote %1").arg(executableConnectHostPort())); @@ -1363,10 +1399,11 @@ void SeerGdbWidget::handleGdbCoreFileExecutable () { handleGdbSourceScripts(); } - // No console for 'core' mode. + // No console for 'core' mode but make sure it's reattached. setExecutableLaunchMode("corefile"); setGdbRecordMode(""); setExecutablePid(0); + reattachConsole(); if (newExecutableFlag() == true) { handleGdbExecutablePreCommands(); // Run any 'pre' commands before program is loaded. @@ -2001,8 +2038,6 @@ void SeerGdbWidget::handleGdbBreakpointCommand (QString breakpoint, QString comm return; } - qDebug().noquote() << "XXX: " << breakpoint << command; - handleGdbCommand("-break-commands " + breakpoint + " \"" + command + "\""); handleGdbGenericpointList(); } @@ -2859,6 +2894,12 @@ void SeerGdbWidget::handleConsoleModeChanged () { } } +void SeerGdbWidget::handleAboutToQuit () { + + // Detect if we're exiting Seer. + setIsQuitting(true); +} + void SeerGdbWidget::writeSettings () { //qDebug() << "Write Settings"; @@ -3070,6 +3111,14 @@ void SeerGdbWidget::readSettings () { } settings.endGroup(); } +bool SeerGdbWidget::isQuitting () const { + return _isQuitting; +} + +void SeerGdbWidget::setIsQuitting (bool f) { + _isQuitting = f; +} + bool SeerGdbWidget::isGdbRuning () const { if (_gdbProcess->state() == QProcess::NotRunning) { @@ -3237,8 +3286,6 @@ void SeerGdbWidget::createConsole () { setConsoleMode(consoleMode()); setConsoleScrollLines(consoleScrollLines()); - - writeLogsSettings(); } } @@ -3275,6 +3322,21 @@ void SeerGdbWidget::disconnectConsole () { } } +void SeerGdbWidget::reattachConsole () { + + if (_consoleIndex < 0) { + return; + } + + if (_consoleWidget == nullptr) { + return; + } + + _consoleMode = "attached"; + + logsTabWidget->reattachTab(_consoleIndex); +} + void SeerGdbWidget::setConsoleMode (const QString& mode) { _consoleMode = mode; diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index 8096c0b..92df8d5 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -194,7 +194,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void readSettings (); public slots: - void handleLogsTabMoved (int from, int to); + void handleLogsTabMoved (int to, int from); void handleLogsTabChanged (int index); void handleRaiseMessageTab (); @@ -334,6 +334,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void handleGdbProcessErrored (QProcess::ProcessError errorStatus); void handleConsoleModeChanged (); + void handleAboutToQuit (); signals: void stoppingPointReached (); @@ -346,6 +347,9 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void readLogsSettings (); private: + bool isQuitting () const; + void setIsQuitting (bool f); + bool isGdbRuning () const; bool startGdb (); bool startGdbRR (); @@ -354,9 +358,11 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void deleteConsole (); void connectConsole (); void disconnectConsole (); + void reattachConsole (); SeerConsoleWidget* console (); void sendGdbInterrupt (int signal); + bool _isQuitting; QString _gdbProgram; QString _gdbArguments; QString _gdbProgramOverride; diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index 6bf33ae..5ab0e24 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -1005,11 +1005,14 @@ void SeerMainWindow::handleText (const QString& text) { return; + }else if (text == "^connected") { + //^connected + return; + }else if (text.startsWith("^connected,frame=")) { //^connected,frame={level=\"0\",addr=\"0x00007f48351f80c1\",func=\"read\",args=[],from=\"/lib64/libc.so.6\",arch=\"i386:x86-64\"}" return; - }else if (text.startsWith("*stopped")) { QString reason_text = Seer::parseFirst(text, "reason=", '"', '"', false); diff --git a/src/SeerUtl.cpp b/src/SeerUtl.cpp index 07be08b..3c2a4ed 100644 --- a/src/SeerUtl.cpp +++ b/src/SeerUtl.cpp @@ -6,6 +6,13 @@ #include #include +// Comment out for now. I don't want to include boost because +// that would impact people try to compile Seer. Qt6 offer +// a 'stacktrace' function. OpenSuse may be slow in adoption. +// For now, comment it out and use when needed. +// #include + +#include #include // @@ -1258,5 +1265,11 @@ namespace Seer { return result; } + + void printStackTrace () { + // Capture and print the stack trace using Boost.Stacktrace. + // See comments at top. + // std::cout << "Stack trace:\n" << boost::stacktrace::stacktrace() << std::endl; + } } diff --git a/src/SeerUtl.h b/src/SeerUtl.h index dffb28f..7323360 100644 --- a/src/SeerUtl.h +++ b/src/SeerUtl.h @@ -31,9 +31,7 @@ namespace Seer { QString elideText (const QString& str, Qt::TextElideMode mode, int length); QStringList split (const QString& str); QString unescape (const QString& str); - int createID (); - unsigned char ebcdicToAscii (unsigned char byte); unsigned char ucharToAscii (unsigned char byte); QString ucharToHex (const QVector& bytes, int from, int count); @@ -47,9 +45,8 @@ namespace Seer { QString ucharToLong (const QVector& bytes, int from, int count); QString ucharToFloat (const QVector& bytes, int from, int count); QString ucharToDouble (const QVector& bytes, int from, int count); - int typeBytes (const QString& type); - bool readFile (const QString& filename, QStringList& lines); + void printStackTrace (); } diff --git a/tests/hellogdbserver/README b/tests/hellogdbserver/README new file mode 100644 index 0000000..e78cc59 --- /dev/null +++ b/tests/hellogdbserver/README @@ -0,0 +1,18 @@ +Notes for debugging hellogdbserver with Seer. + +In one terminal, start gdbserver. + + $ gdbserver :1234 hellogdbserver + +In another terminal, start Seer with the project file. + + $ /usr/local/bin/seergdb -xxx -s --project project.seer + + +When exiting Seer, make sure to enter this command into the +gdb command field. Otherwise, the gdbserver process will hang +and you will need to 'kill -9' the gdbserver process. + + (gdb) monitor exit + +