Bug 342888 - Cantor crashing when typing some keys in worksheet
Summary: Cantor crashing when typing some keys in worksheet
Status: RESOLVED FIXED
Alias: None
Product: cantor
Classification: Applications
Component: general (show other bugs)
Version: unspecified
Platform: Compiled Sources Linux
: NOR grave
Target Milestone: ---
Assignee: Filipe Saraiva
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-01-15 21:45 UTC by Filipe Saraiva
Modified: 2015-02-03 13:27 UTC (History)
2 users (show)

See Also:
Latest Commit:
Version Fixed In:


Attachments
Diff between commandentry.cpp of Cantor Qt4/KDELibs4 and Cantor Qt5/KF5 (6.25 KB, patch)
2015-01-30 22:02 UTC, Filipe Saraiva
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Filipe Saraiva 2015-01-15 21:45:14 UTC
Cantor frameworks'branch is crashing when the user type some keys in worksheet. I can confirm this bug with Python 2, Python 3, and Lua backends (I need to test the others). Maybe the problem is related with some core part.

Reproducible: Always

Steps to Reproduce:
1. Select some backend (for example, Python 2);
2. Type "num" (without ") and press TAB;
3. Press "." (without ");
4. Cantor crash.
Comment 1 Minh Ngo 2015-01-25 16:02:35 UTC
Someone has deleted m_completionObject before...


p m_completionBox
$1 = {wp = {d = 0xaccae0, value = 0xab9040}}
(gdb) p m_completionObject
p m_completionObject
$2 = (Cantor::CompletionObject *) 0x0
(gdb) bt
bt
#0 0x00000031df21c964 in KCompletion::allMatches() (this=0x0) at ../../src/kcompletion.cpp:395
#1 0x00007fffe3b9fcd4 in CommandEntry::showCompletions() (this=0x986310) at /home/ignotus/Development/cantor/src/commandentry.cpp:442
#2 0x00007fffe3bc143e in CommandEntry::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x986310, _c=QMetaObject::InvokeMetaMethod, _id=11, _a=0x7fffffffcb70) at /home/ignotus/Development/cantor/build/src/moc_commandentry.cpp:180
#3 0x00000032b9ebdac9 in QMetaObject::activate(QObject*, int, int, void**) (sender=0x949380, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=0x0) at kernel/qobject.cpp:3716
#4 0x00007ffff7bc425b in Cantor::CompletionObject::done() (this=0x949380) at /home/ignotus/Development/cantor/build/src/lib/moc_completionobject.cpp:197
#5 0x00007ffff7bb7891 in Cantor::CompletionObject::findCompletion() (this=0x949380) at /home/ignotus/Development/cantor/src/lib/completionobject.cpp:185
#6 0x00007ffff7bb9463 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (Cantor::CompletionObject::*)()>::call(void (Cantor::CompletionObject::*)(), Cantor::CompletionObject*, void**) (f=(void (Cantor::CompletionObject::*)(Cantor::CompletionObject * const)) 0x7ffff7bb7738 <Cantor::CompletionObject::findCompletion()>, o=0x949380, arg=0x7fffffffcdd0) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:500
#7 0x00007ffff7bb933c in QtPrivate::FunctionPointer<void (Cantor::CompletionObject::*)()>::call<QtPrivate::List<>, void>(void (Cantor::CompletionObject::*)(), Cantor::CompletionObject*, void**) (f=(void (Cantor::CompletionObject::*)(Cantor::CompletionObject * const)) 0x7ffff7bb7738 <Cantor::CompletionObject::findCompletion()>, o=0x949380, arg=0x7fffffffcdd0) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:519
#8 0x00007ffff7bb90e7 in QtPrivate::QSlotObject<void (Cantor::CompletionObject::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0x969b60, r=0x949380, a=0x7fffffffcdd0, ret=0x0) at /usr/include/qt5/QtCore/qobject_impl.h:143
#9 0x00000032b9ebd45a in QMetaObject::activate(QObject*, int, int, void**) (a=0x7fffffffcdd0, r=0x949380, this=0x969b60) at ../../src/corelib/kernel/qobject_impl.h:124
#10 0x00000032b9ebd45a in QMetaObject::activate(QObject*, int, int, void**) (sender=0x949380, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=0x0) at kernel/qobject.cpp:3702
#11 0x00007ffff7bc41e7 in Cantor::CompletionObject::fetchingDone() (this=0x949380) at /home/ignotus/Development/cantor/build/src/lib/moc_completionobject.cpp:184
#12 0x00007fffe8418af0 in PythonCompletionObject::fetchCompletions() (this=0x949380) at /home/ignotus/Development/cantor/src/backends/python/pythoncompletionobject.cpp:48
#13 0x00007ffff7bc3f36 in Cantor::CompletionObject::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x949380, _c=QMetaObject::InvokeMetaMethod, _id=4, _a=0x8f1420) at /home/ignotus/Development/cantor/build/src/lib/moc_completionobject.cpp:108
#14 0x00000032b9ebec2a in QObject::event(QEvent*) (this=0x949380, e=<optimized out>) at kernel/qobject.cpp:1245
#15 0x00000031dc35ad3c in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=this@entry=0x637ac0, receiver=receiver@entry=0x949380, e=e@entry=0xa2a870) at kernel/qapplication.cpp:3722
#16 0x00000031dc360330 in QApplication::notify(QObject*, QEvent*) (this=0x7fffffffde10, receiver=0x949380, e=0xa2a870) at kernel/qapplication.cpp:3505
#17 0x00000032b9e8e4ab in QCoreApplication::notifyInternal(QObject*, QEvent*) (this=0x7fffffffde10, receiver=0x949380, event=event@entry=0xa2a870) at kernel/qcoreapplication.cpp:932
#18 0x00000032b9e904eb in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (event=0xa2a870, receiver=<optimized out>) at kernel/qcoreapplication.h:228
#19 0x00000032b9e904eb in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (receiver=receiver@entry=0x0, event_type=event_type@entry=0, data=0x635f50) at kernel/qcoreapplication.cpp:1536
#20 0x00000032b9e90ae8 in QCoreApplication::sendPostedEvents(QObject*, int) (receiver=receiver@entry=0x0, event_type=event_type@entry=0) at kernel/qcoreapplication.cpp:1394
#21 0x00000031df22343f in KCompletionBox::setVisible(bool) (this=0x8f5500, visible=<optimized out>) at ../../src/kcompletionbox.cpp:350
#22 0x00007fffe3b9ff8f in CommandEntry::showCompletions() (this=0x986310) at /home/ignotus/Development/cantor/src/commandentry.cpp:454
#23 0x00007fffe3bc143e in CommandEntry::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x986310, _c=QMetaObject::InvokeMetaMethod, _id=11, _a=0x7fffffffd4b0) at /home/ignotus/Development/cantor/build/src/moc_commandentry.cpp:180
#24 0x00000032b9ebdac9 in QMetaObject::activate(QObject*, int, int, void**) (sender=0x949380, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=0x0) at kernel/qobject.cpp:3716
#25 0x00007ffff7bc425b in Cantor::CompletionObject::done() (this=0x949380) at /home/ignotus/Development/cantor/build/src/lib/moc_completionobject.cpp:197
#26 0x00007ffff7bb7891 in Cantor::CompletionObject::findCompletion() (this=0x949380) at /home/ignotus/Development/cantor/src/lib/completionobject.cpp:185
#27 0x00007ffff7bb9463 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (Cantor::CompletionObject::*)()>::call(void (Cantor::CompletionObject::*)(), Cantor::CompletionObject*, void**) (f=(void (Cantor::CompletionObject::*)(Cantor::CompletionObject * const)) 0x7ffff7bb7738 <Cantor::CompletionObject::findCompletion()>, o=0x949380, arg=0x7fffffffd710) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:500
#28 0x00007ffff7bb933c in QtPrivate::FunctionPointer<void (Cantor::CompletionObject::*)()>::call<QtPrivate::List<>, void>(void (Cantor::CompletionObject::*)(), Cantor::CompletionObject*, void**) (f=(void (Cantor::CompletionObject::*)(Cantor::CompletionObject * const)) 0x7ffff7bb7738 <Cantor::CompletionObject::findCompletion()>, o=0x949380, arg=0x7fffffffd710) at /usr/include/qt5/QtCore/qobjectdefs_impl.h:519
#29 0x00007ffff7bb90e7 in QtPrivate::QSlotObject<void (Cantor::CompletionObject::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) (which=1, this_=0x969b60, r=0x949380, a=0x7fffffffd710, ret=0x0) at /usr/include/qt5/QtCore/qobject_impl.h:143
#30 0x00000032b9ebd45a in QMetaObject::activate(QObject*, int, int, void**) (a=0x7fffffffd710, r=0x949380, this=0x969b60) at ../../src/corelib/kernel/qobject_impl.h:124
#31 0x00000032b9ebd45a in QMetaObject::activate(QObject*, int, int, void**) (sender=0x949380, signalOffset=<optimized out>, local_signal_index=<optimized out>, argv=0x0) at kernel/qobject.cpp:3702
#32 0x00007ffff7bc41e7 in Cantor::CompletionObject::fetchingDone() (this=0x949380) at /home/ignotus/Development/cantor/build/src/lib/moc_completionobject.cpp:184
#33 0x00007fffe8418af0 in PythonCompletionObject::fetchCompletions() (this=0x949380) at /home/ignotus/Development/cantor/src/backends/python/pythoncompletionobject.cpp:48
#34 0x00007ffff7bc3f36 in Cantor::CompletionObject::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) (_o=0x949380, _c=QMetaObject::InvokeMetaMethod, _id=4, _a=0xab4c70) at /home/ignotus/Development/cantor/build/src/lib/moc_completionobject.cpp:108
#35 0x00000032b9ebec2a in QObject::event(QEvent*) (this=0x949380, e=<optimized out>) at kernel/qobject.cpp:1245
#36 0x00000031dc35ad3c in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=this@entry=0x637ac0, receiver=receiver@entry=0x949380, e=e@entry=0xa9a240) at kernel/qapplication.cpp:3722
#37 0x00000031dc360330 in QApplication::notify(QObject*, QEvent*) (this=0x7fffffffde10, receiver=0x949380, e=0xa9a240) at kernel/qapplication.cpp:3505
#38 0x00000032b9e8e4ab in QCoreApplication::notifyInternal(QObject*, QEvent*) (this=0x7fffffffde10, receiver=0x949380, event=event@entry=0xa9a240) at kernel/qcoreapplication.cpp:932
#39 0x00000032b9e904eb in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (event=0xa9a240, receiver=<optimized out>) at kernel/qcoreapplication.h:228
#40 0x00000032b9e904eb in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (receiver=receiver@entry=0x0, event_type=event_type@entry=0, data=0x635f50) at kernel/qcoreapplication.cpp:1536
#41 0x00000032b9e90ae8 in QCoreApplication::sendPostedEvents(QObject*, int) (receiver=receiver@entry=0x0, event_type=event_type@entry=0) at kernel/qcoreapplication.cpp:1394
#42 0x00000032b9ee5333 in postEventSourceDispatch(GSource*, GSourceFunc, gpointer) (s=0x665e20) at kernel/qeventdispatcher_glib.cpp:271
#43 0x0000003a1f249aeb in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#44 0x0000003a1f249e88 in g_main_context_iterate.isra () at /lib64/libglib-2.0.so.0
#45 0x0000003a1f249f3c in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#46 0x00000032b9ee5727 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (this=0x665eb0, flags=...) at kernel/qeventdispatcher_glib.cpp:418
#47 0x00000032b9e8bd42 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (this=this@entry=0x7fffffffdd70, flags=..., flags@entry=...) at kernel/qeventloop.cpp:204
#48 0x00000032b9e937ec in QCoreApplication::exec() () at kernel/qcoreapplication.cpp:1185
#49 0x000000000041603f in main(int, char**) (argc=1, argv=0x7fffffffe3b8) at /home/ignotus/Development/cantor/src/main.cpp:109
Comment 2 Minh Ngo 2015-01-25 16:21:50 UTC
I suppose after the first completion (num -> numpy) an instance CompletionObject emits a signal done() and then some object outside has removed it through deleteLater...
Comment 3 Filipe Saraiva 2015-01-30 21:59:03 UTC
I made some debugs here, maybe the problem is related with commandentry.cpp line 449:

connect(m_commandItem->document(), SIGNAL(contentsChanged()), this, SLOT(completedLineChanged()));

This line creates the connection to generate a new list of elements to populate the popup menu when the command is changed. If you comment this line we don't have the problem and don't have changes in first popup menu. =D

When I run Cantor Qt4/KDELibs4 I can see the new list of elements being generated once. In line 271 I run the tab-completion to numpy command https://paste.kde.org/pljyxuwoq#line-271 and in line 289 the tab-completion generate the elements to numpy. command https://paste.kde.org/pljyxuwoq#line-289

In Cantor Qt5/KF5 we can see a sequence of process to generate elements to a same command. Line 240 generate the elements to numpy command https://paste.kde.org/pn4m2dmlq#line-240 and line 253 to numpy. command https://paste.kde.org/pn4m2dmlq#line-253. How we can see, these same elements will be generate again in line 263. I think the screen frozen is caused by a infinite loop in this generation of elements to tab-completion.

We need to follow the flow of execution to identify where is this problem.
Comment 4 Filipe Saraiva 2015-01-30 22:02:55 UTC
Created attachment 90821 [details]
Diff between commandentry.cpp of Cantor Qt4/KDELibs4 and Cantor Qt5/KF5
Comment 5 Filipe Saraiva 2015-01-30 22:04:31 UTC
In attachment above, the diff between commandentry.cpp of Cantor Qt4/KDELibs4 and Cantor Qt5/KF5. Maybe nothing really important there - except, maybe, the new SIGNAL/SLOT connection style.
Comment 6 Lucas Hermann Negri 2015-01-31 17:05:07 UTC
I think the problem lies in calling removeContextHelp during a completion. It is the only point where the m_completionObject is marked for deletion and the pointer is set to 0.

Commenting the "delete and set to 0" makes the completions work as expected.

I've reproduced the bug in Python 3 backend, but not in the Lua backend. And I think I know why: the Lua backend does not provides context help, so the removeContextHelp was not being called this way.
Comment 7 Filipe Saraiva 2015-01-31 18:41:40 UTC
Very nice Lucas, thank you. There are some problems yet, for example if you type "numpy" and call the completions, you can not to erase the "numpy" without press ESC key (the completion suggestion is not hide).

But it is the way to fix the problem, thank you again. Let's continue to research the solution for this bug.
Comment 8 Lucas Hermann Negri 2015-02-01 14:36:45 UTC
I've traced the execution to see what is exactly happening. This is what I've got after typing tab after typing the text "p" to get the completions in the Python 3 backend:

1) setCompletion, m_completionObject is now 0x10e2f50
2) showCompletion, m_completionObject remains 0x10e2f50
3) removeContextHelp is called, m_completionObject is now 0. At this point, the completion list is not visible
4) the completion menu is now shown, but selecting an item will call a method on the invalid m_completionObject

At 3), removeContextHelp is called at line 538 in commandentry.cpp .
Comment 9 Filipe Saraiva 2015-02-02 10:10:40 UTC
Hi Lucas, where is 4) called?
Comment 10 Lucas Hermann Negri 2015-02-02 11:10:48 UTC
I think it is called by a signal, as the backtrace is polluted with Qt signal/slot mechanism calls.
Comment 11 Filipe Saraiva 2015-02-03 00:43:38 UTC
Hello guys, after a lot of work putting qDebug in almost all functions to follow the flow of the program, I found the error.

Well, looks like just the signal connection (line 423) was following a different syntax of the signal disconnection (line 429), then the signal always ran a same function, CommandEntry::showCompletions, when it needs to alternate between CommandEntry::showCompletions and CommandEntry::updateCompletions.

The patch is in https://git.reviewboard.kde.org/r/122397/, I did some tests with Python 2 and 3, Lua, and Octave. All working as Cantor stable version, however Octave have a different problem, when you select some entry of tab-complete it is not presented in worksheet - but it is a different problem.

So, please make some tests and if it is all ok I will push to repository.

o/
Comment 12 Filipe Saraiva 2015-02-03 09:48:06 UTC
Git commit 5357b125c85bf15817d956e4d642d74d580e8034 by Filipe Saraiva.
Committed on 03/02/2015 at 09:35.
Pushed by filipesaraiva into branch 'frameworks'.

Fix tab-complete
REVIEW: 122397

M  +2    -2    src/commandentry.cpp

http://commits.kde.org/cantor/5357b125c85bf15817d956e4d642d74d580e8034