Summary: | Kdevelop crashes on watch member variable | ||
---|---|---|---|
Product: | [Applications] kdevelop | Reporter: | Ian H <master.haber> |
Component: | CPP Debugger | Assignee: | kdevelop-bugs-null |
Status: | CLOSED UPSTREAM | ||
Severity: | normal | CC: | niko.sams, pfyu817 |
Priority: | NOR | ||
Version: | 5.1.0 | ||
Target Milestone: | --- | ||
Platform: | Appimage | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: | |||
Attachments: |
Debug output for debugger
Proposed patch GDB outputs when watchpoint goes out of scope Log file for the test case Better handle and report debugger errors |
Description
Ian H
2017-02-17 19:34:30 UTC
Please retrieve a backtrace of the crash. See: https://community.kde.org/Guidelines_and_HOWTOs/Debugging/How_to_create_useful_crash_reports so i've never been able to get a backtrace while using the appimage. I attempted to build source today, but it seems there are build errors in master at the moment. how do i set kdesrc-build to use branch 5.1 for kdevelop and kdevplatform? I attempted to modify the .kdesrc-buildrc and set it to use branch 5.1, but it attempts to use svn instead of git and then fails to update. FWIW, master should build fine according to CI. If you want to switch branches I *think* you should be able to use this: module kdevelop branch-group kf5-qt5 ... If that doesn't work you can still simply just `git checkout 5.1; make; make install` in both the kdevplatform + kdevelop dir. I get this build error when i attempt to build master. what module is KUrlRequester in that i'm assuming i need to add to the list of things to download and update. /home/ian/kdesrc/kdevelop/languages/plugins/custom-definesandincludes/compilerprovider/widget/compilerswidget.cpp:81:34: error: ‘textEdited’ is not a member of ‘KUrlRequester’ connect(m_ui->compilerPath, &KUrlRequester::textEdited, this, &CompilersWidget::compilerEdited); True, this got added just recently. I've restored compat with KF5 5.15 now. See: commit 2c775c07436107f90bec8ee16b73f4e5258f362d Author: Kevin Funk <kfunk@kde.org> Date: Fri Feb 17 23:32:22 2017 +0100 Restore compat with KF5 5.15 The signal KUrlRequester::textEdited got only added in 5.21 Please try to compile again here is the backtrace. it also looks like i got a message saying 'breakpoint doesn't contain required location/expression data'. maybe that has something to do with it Thread 1 "kdevelop" received signal SIGSEGV, Segmentation fault. 0x00007fffb263a07e in KDevMI::MI::MICommand::markAsCompleted() () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so (gdb) bt #0 0x00007fffb263a07e in KDevMI::MI::MICommand::markAsCompleted() () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so #1 0x00007fffb263bd9d in KDevMI::MIDebugger::processLine(QByteArray const&) () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so #2 0x00007fffb263b506 in KDevMI::MIDebugger::readyReadStandardOutput() () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so #3 0x00007fffb263e308 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KDevMI::MIDebugger::*)()>::call(void (KDevMI::MIDebugger::*)(), KDevMI::MIDebugger*, void**) () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so #4 0x00007fffb263e1ca in void QtPrivate::FunctionPointer<void (KDevMI::MIDebugger::*)()>::call<QtPrivate::List<>, void>(void (KDevMI::MIDebugger::*)(), KDevMI::MIDebugger*, void**) () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so #5 0x00007fffb263ded1 in QtPrivate::QSlotObject<void (KDevMI::MIDebugger::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) () from /home/ian/kde-5/lib/x86_64-linux-gnu/plugins/kdevplatform/27/kdevgdb.so #6 0x00007ffff5d35baf in QtPrivate::QSlotObjectBase::call (a=0x7fffffffcfa0, r=0x6c72030, this=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qobject_impl.h:124 #7 QMetaObject::activate (sender=sender@entry=0x6c72120, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=5, argv=argv@entry=0x0) at kernel/qobject.cpp:3698 #8 0x00007ffff5d36537 in QMetaObject::activate (sender=sender@entry=0x6c72120, m=m@entry=0x7ffff5f4c400 <QProcess::staticMetaObject>, local_signal_index=local_signal_index@entry=5, argv=argv@entry=0x0) at kernel/qobject.cpp:3578 #9 0x00007ffff5c34b63 in QProcess::readyReadStandardOutput (this=this@entry=0x6c72120) at .moc/moc_qprocess.cpp:266 ---Type <return> to continue, or q <return> to quit--- #10 0x00007ffff5c3d0c2 in QProcessPrivate::tryReadFromChannel (this=0x6c72140, channel=0x6c72270) at io/qprocess.cpp:966 #11 0x00007ffff5c3d540 in QProcessPrivate::_q_canReadStandardOutput (this=<optimized out>) at io/qprocess.cpp:977 #12 QProcess::qt_static_metacall (_o=<optimized out>, _c=<optimized out>, _id=<optimized out>, _a=0x7fffffffd1a0) at .moc/moc_qprocess.cpp:133 #13 0x00007ffff5d35d2a in QMetaObject::activate (sender=sender@entry=0x6c72ec0, signalOffset=<optimized out>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x7fffffffd1a0) at kernel/qobject.cpp:3713 #14 0x00007ffff5d36537 in QMetaObject::activate (sender=sender@entry=0x6c72ec0, m=m@entry=0x7ffff5f50780 <QSocketNotifier::staticMetaObject>, local_signal_index=local_signal_index@entry=0, argv=argv@entry=0x7fffffffd1a0) at kernel/qobject.cpp:3578 #15 0x00007ffff5db524e in QSocketNotifier::activated (this=this@entry=0x6c72ec0, _t1=82) at .moc/moc_qsocketnotifier.cpp:134 #16 0x00007ffff5d421cb in QSocketNotifier::event (this=0x6c72ec0, e=<optimized out>) at kernel/qsocketnotifier.cpp:260 #17 0x00007ffff65fa05c in QApplicationPrivate::notify_helper (this=this@entry=0x647190, receiver=receiver@entry=0x6c72ec0, e=e@entry=0x7fffffffd410) at kernel/qapplication.cpp:3716 #18 0x00007ffff65ff516 in QApplication::notify (this=0x7fffffffd970, receiver=0x6c72ec0, e=0x7fffffffd410) at kernel/qapplication.cpp:3499 #19 0x00007ffff5d0738b in QCoreApplication::notifyInternal (this=0x7fffffffd970, receiver=0x6c72ec0, event=event@entry=0x7fffffffd410) at kernel/qcoreapplication.cpp:965 #20 0x00007ffff5d5dc95 in QCoreApplication::sendEvent (event=0x7fffffffd410, receiver=<optimized out>) at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:224 #21 socketNotifierSourceDispatch (source=0x7659a0) at kernel/qeventdispatcher_glib.cpp:101 #22 0x00007fffee394197 in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #23 0x00007fffee3943f0 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #24 0x00007fffee39449c in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0 #25 0x00007ffff5d5d7cf in QEventDispatcherGlib::processEvents (this=0x765850, flags=...) at kernel/qeventdispatcher_glib.cpp:418 #26 0x00007ffff5d04b4a in QEventLoop::exec (this=this@entry=0x7fffffffd620, flags=..., flags@entry=...) at kernel/qeventloop.cpp:204 #27 0x00007ffff5d0cbec in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1229 #28 0x000000000040e79e in main () if you need anything else from gdb, i still have it up and will get back to you on monday. Hi Ion, from the backtrace it's not clear what's going wrong here. There's no abnormal pointer access in the frame 0 of the backtrace. Could you also provide the console output when crashing? The debugger plugin related logs are disabled by default, you can enable it by starting kdevelop like this inside console: QT_LOGGING_RULES="kdevelop.debuggers.gdb.debug=true;kdevelop.debuggers.common.debug=true" kdevelop with those debug messages, i get the same backtrace as before, but i get QMetaObject::invokeMethod: No such method ExpandingTree::scrollTo(QModelIndex,QAbstractItemView::ScrollHint) Breakpoint doesn't contain required location/expression data before it. i would assume though that you could recreate this. it is 100% for me. Hmm actually I can't reproduce this. I tried with a structure member variable and it works as intended. From the log output, kdevelop was complaining about gdb not returning required data. So my guessing is something went wrong with either the gdb itself or the way we were setting breakpoints. How do you exactly set break on change? By manually using the gdb console or by hovering on the variable and click "stop on change" button? Also, I'm expecting some log output with the prefix "kdevelop.debuggers.common:" and related to the internal interaction between kdevelop and gdb. Could you paste the full log output? I get the crash regardless of how i set the breakpoint. i can set it in gdb or through kdevelop and both will crash. the only logging stuff i got was qt.core.logging: Ignoring malformed logging rule: 'kdevelop.debuggers.gdb.debug=true;kdevelop.debuggers.common.debug=true' at the start of the program and kdevelop.debuggers.common: "No environment group specified, looks like a broken configuration, please check run configuration 'xxxxxx'. Using default environment group." during the startup of my program. 'Breakpoint doesn't contain required location/expression data' is logged when i create the breakpoint. There is nothing after that before the backtrace. I see. Seems your Qt version doesn't support semicolon separated logging rules. Instead, create a file named logging.conf with the following content: [Rules] kdevelop.debuggers.gdb.debug=true kdevelop.debuggers.common.debug=true And launch kdevelop with QT_LOGGING_CONF='/path/to/logging.conf' kdevelop I think the crash might be specific to some particular gdb version. But without detailed logging, I can't tell anything yet. Created attachment 104134 [details]
Debug output for debugger
Here is the output. my gdb version:
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Please also try valgrind, that is usually much more helpful in such situations: valgrind --smc-check=all-non-file --track-origins=yes kdevelop Okay. So setting watch point itself seems normal in log. The crash actually happens before the watch point was triggered. gdb returned two replies for 35-exec-continue command: 35^running and 35^error,msg=\"Command aborted.\" This doesn't confirm to the spec and confused kdevelop which assumes each reply must have a corresponding command. I will fix this by ignoring wild replies from gdb. Please try if my patch fixes the crash. But this is likely also a bug within gdb itself. I would suggest verify if debugging directly in gdb command line works with your program if there's still something wrong. (Probably something like the program doesn't resume execution because the exec-continue command failed) Created attachment 104135 [details]
Proposed patch
The patch does prevent the crash, although as you suggested, gdb is just sitting there hanging now. Messing with the gdb console outside of kdevelop led me to something interesting. if i use the command 'watch m_bInUpdate', when i attempt to continue, it will just say "current stack frame does not contain a variable named 'this'" and not do anything. If i use the command 'watch this.m_bInUpdate', it works as i would expect. Could it be that when kdevelop adds a watch for member variables it just uses 'watch <varname>'? That being said, if this were the case, i would expect that it would be causing issues for everyone. Created attachment 104154 [details]
GDB outputs when watchpoint goes out of scope
Yes, kdevelop uses plain variable name when adding watch points for member variables. This however should work because gdb will delete all invalid watchpoints when the execution left valid scope.
I've created a minimal test program to trigger this problem:
struct testStruct {
int a; int b;
void bar() {
a = a + 1;
}
};
int main() {
testStruct ts;
ts.a = ts.b = 0;
ts.bar();
ts.b++;
return 0;
}
After compile and load it in gdb, this is what I got:
1. break at line 4
2. watch a
3. continue and gdb stopped after a = a + 1 because of watchpoint hit
4. continue again and gdb stopped at some random point after leaving testStruct::bar() with the following output
Error evaluating expression for watchpoint 2
current stack frame does not contain a variable named `this'
Watchpoint 2 deleted.
5. continue and the program exits normally.
If I use watch this.a instead, the outcome is almost the same with the only difference being the warning from gdb:
Watchpoint 3 deleted because the program has left the block in
which its expression is valid.
I've attached the full output from gdb. The point here is that gdb should be able to delete invalid watchpoint gracefully regardless it was set as "this.<varname>" or "<varname>". And it shouldn't produce malformed output in its machine interface which kdevelop uses.
That being said, I'm using a newer version of gdb than yours, so probably the behavior changed. Ian, are you getting the same behavior using my test program?
ran the test case, it does not give me the same behavior. i'm currently modifying it to see if i can reproduce the issue. As far as i can tell, the only differences between my current version of the test and my normal source is that the method i'm attempting to use this on is a slot... but in qt, pretty much everything is a slot or called by a slot. I have created a simple test program that causes the crash. //main.cpp int main(int argc, char* argv[]) { QApplication applicationInstance(argc, argv); testGDBCrash crasher; if (crasher.exec() != QDialog::Accepted) return 0; return applicationInstance.exec(); } //testGDBCrash.h #ifndef TESTGDBCRASH_H #define TESTGDBCRASH_H #include <QDialog> #include <QObject> class testGDBCrash : public QDialog { Q_OBJECT public: testGDBCrash(QWidget * parent=0); Q_SLOT void TestCrash(); bool m_bInUpdate; }; #endif // TESTGDBCRASH_H //testGDBCrash.cpp #include "testGDBCrash.h" #include <QPushButton> #include <QHBoxLayout> testGDBCrash::testGDBCrash(QWidget* parent):QDialog(parent) { resize(200,100); QHBoxLayout * layout=new QHBoxLayout(this); QPushButton * pb=new QPushButton("crash",this); layout->addWidget(pb); setLayout(layout); show(); m_bInUpdate=false; connect(pb,SIGNAL(clicked()),this,SLOT(TestCrash())); } void testGDBCrash::TestCrash() { if(m_bInUpdate) return; m_bInUpdate=false; m_bInUpdate=true; m_bInUpdate=false; } Steps to crash: 1. Run 2. put a breakpoint on line 18 of testGDBCrash.cpp (the if statement) 3. break on change for m_bInUpdate 4. Continue 5. Watch crash. Created attachment 104158 [details]
Log file for the test case
Here is the log file for the test case i created.
Okay I can reproduce your issue now. I guess the difference is that yours is multi-threaded (several threads for qt internal stuff). And when gdb stopped, it stopped at another thread different from the main thread. Probably gdb can't handle this case well. However I'm afraid there's no much I can do on the kdevelop side. As it's hard to distinguish a member variable from normal ones, and it's unclear whether this is the only condition that would trigger the bug. Maybe you should report this to gdb. In the mean time, as a workaround, you can set watchpoints in the Breakpoints tool view manually, using "this.<varname>" as the location. This works as intended. Created attachment 104160 [details]
Better handle and report debugger errors
Anyway, I've updated my patch to better report and end the debug session in this case.
would it be possible to maybe have some sort of manually set variable that would be a prefix for member variables? a lot of us use a very specific member variable prefix, so if it starts with that prefix, chances are it is a member? it is also possible to determine if the variable was declared in the current scope by using 'info locals', right? so any variable not in 'info locals' would be a member? Well adding an UI to set prefix and extra code to identify and match member variable just sounds too much for a workaround for some bug in gdb that will eventually be fixed. For the "info locals", there are also global and static variables that are not member variable. There are too many corner cases, not to even mention single variable is only the simplest case for watchpoint[1]. [1] https://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html Alright. I posted in the gdb bugtracking https://sourceware.org/bugzilla/show_bug.cgi?id=21192 hopefully they will fix it eventually. Thank you for reporting! I've also added a link pointing back to this bug in their bug tracker. |