Bug 345294

Summary: Hang in exiting konsole with Ctrl+D with QInputMethodQuery
Product: [Applications] konsole Reporter: Takahiro Hashimoto <kenya888>
Component: generalAssignee: Konsole Developer <konsole-devel>
Status: RESOLVED FIXED    
Severity: crash CC: khindenburg
Priority: NOR    
Version: 3.90.900   
Target Milestone: ---   
Platform: Compiled Sources   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:
Attachments: a patch to fix konsole hang when exiting

Description Takahiro Hashimoto 2015-03-18 05:53:33 UTC
Created attachment 91614 [details]
a patch to fix konsole hang when exiting

[ Environment ]
 - Fedora 21 or Gentoo
 - Kernel 3.18/3.19
 - gcc 4.8.3/4.9.2
 - Qt 5.4.1(build from git repo)
 - KF5 latest(build with kdesrc-build)
 - konsole (commit 9f8d3933940744cf8eca50d57558bfac82eb0ee7)

[ How to reproduce ]
 - Launch Konsole
 - Operate some work
 - Exit with Ctrl+D(quit bash)

[ Expected behavior ]
 - Konsole exits gracefully

[ Fact behavior ]
 - Konsole hangs (not crash)

[ Frequency of occurrence ]
 - very often

[Additional info]
 - I use qimsys(http://git.qtquick.me/?p=qimsys.git;a=summary), Japanese input method written with Qt and qimsys requests QInputMethodQueryEvent to Konsole

[Solution]
 - proposed a patch (see attached)

[Investigation]

I have found missing incrementation of for loop around "src/TerminalCharacterDecoder.cpp:114"

backtrace: 
(gdb) bt
#0  0x00007fca51bee939 in QHash<unsigned short, unsigned short*>::value(unsigned short const&) const (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, akey=@0x7ffcc0680f14: 42168) at /opt/qt/5.4/include/QtCore/qhash.h:615
#1  0x00007fca51bee379 in QHash<unsigned short, unsigned short*>::operator[](unsigned short const&) const (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, akey=@0x7ffcc0680f14: 42168) at /opt/qt/5.4/include/QtCore/qhash.h:743
Python Exception <type 'exceptions.RuntimeError'> maximum recursion depth exceeded: 
#2  0x00007fca51beda71 in Konsole::ExtendedCharTable::lookupExtendedChar(unsigned short, unsigned short&) const (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, hash=42168, length=@0x7ffcc0680f6a: 0) at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/ExtendedCharTable.cpp:118
#3  0x00007fca51bec202 in Konsole::PlainTextDecoder::decodeLine(Konsole::Character const*, int, unsigned char) (this=0x7ffcc0680fe0, characters=0xb0e2a0, count=155)
    at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/TerminalCharacterDecoder.cpp:114
#4  0x00007fca51bfc04f in Konsole::TerminalDisplay::inputMethodQuery(Qt::InputMethodQuery) const (this=0x9def90, query=Qt::ImSurroundingText)
    at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/TerminalDisplay.cpp:2913
#5  0x00007fca4c5d1dc1 in QWidget::event(QEvent*) (this=0x9def90, event=0x7ffcc0681b30) at /home/thashimo/devel/qt5/qtbase/src/widgets/kernel/qwidget.cpp:8739
#6  0x00007fca51bfc9fd in Konsole::TerminalDisplay::event(QEvent*) (this=0x9def90, event=0x7ffcc0681b30)
    at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/TerminalDisplay.cpp:3120
#7  0x00007fca4c582408 in QApplicationPrivate::notify_helper(QObject*, QEvent*) (this=0x6c0420, receiver=0x9def90, e=0x7ffcc0681b30)
    at /home/thashimo/devel/qt5/qtbase/src/widgets/kernel/qapplication.cpp:3722


(gdb) f 0
#0  0x00007fca51bee939 in QHash<unsigned short, unsigned short*>::value (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, akey=@0x7ffcc0680f14: 42168)
    at /opt/qt/5.4/include/QtCore/qhash.h:615
615	Q_INLINE_TEMPLATE const T QHash<Key, T>::value(const Key &akey) const
(gdb) f 1 
#1  0x00007fca51bee379 in QHash<unsigned short, unsigned short*>::operator[] (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, akey=@0x7ffcc0680f14: 42168)
    at /opt/qt/5.4/include/QtCore/qhash.h:743
743	    return value(akey);
(gdb) f 2 
Python Exception <type 'exceptions.RuntimeError'> maximum recursion depth exceeded: 
#2  0x00007fca51beda71 in Konsole::ExtendedCharTable::lookupExtendedChar (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, hash=42168, 
    length=@0x7ffcc0680f6a: 0) at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/ExtendedCharTable.cpp:118
118	    ushort* buffer = extendedCharTable[hash];
(gdb) down
#1  0x00007fca51bee379 in QHash<unsigned short, unsigned short*>::operator[] (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, akey=@0x7ffcc0680f14: 42168)
    at /opt/qt/5.4/include/QtCore/qhash.h:743
743	    return value(akey);
(gdb) up
Python Exception <type 'exceptions.RuntimeError'> maximum recursion depth exceeded: 
#2  0x00007fca51beda71 in Konsole::ExtendedCharTable::lookupExtendedChar (this=0x7fca51ea1790 <Konsole::ExtendedCharTable::instance>, hash=42168, 
    length=@0x7ffcc0680f6a: 0) at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/ExtendedCharTable.cpp:118
118	    ushort* buffer = extendedCharTable[hash];
(gdb) up
#3  0x00007fca51bec202 in Konsole::PlainTextDecoder::decodeLine (this=0x7ffcc0680fe0, characters=0xb0e2a0, count=155)
    at /home/thashimo/devel/kf5/src/kde/applications/konsole/src/TerminalCharacterDecoder.cpp:114
114	            const ushort* chars = ExtendedCharTable::instance.lookupExtendedChar(characters[i].character, extendedCharLength);
(gdb) list
109	    }
110	
111	    for (int i = 0; i < outputCount;) {
112	        if (characters[i].rendition & RE_EXTENDED_CHAR) {
113	            ushort extendedCharLength = 0;
114	            const ushort* chars = ExtendedCharTable::instance.lookupExtendedChar(characters[i].character, extendedCharLength);
115	            if (chars) {
116	                const QString s = QString::fromUtf16(chars, extendedCharLength);
117	                plainText.append(s);
118	                i += qMax(1, string_width(s));
(gdb) list
119	            }
120	        } else {
121	            // All characters which appear before the last real character are
122	            // seen as real characters, even when they are technically marked as
123	            // non-real.
124	            //
125	            // This feels tricky, but otherwise leading "whitespaces" may be
126	            // lost in some situation. One typical example is copying the result
127	            // of `dialog --infobox "qwe" 10 10` .
128	            if (characters[i].isRealCharacter || i <= realCharacterGuard) {
Comment 1 Kurt Hindenburg 2015-03-28 19:17:39 UTC
Git commit 7017a999d620562f7e51fd11303630bd0c4bf2ff by Kurt Hindenburg.
Committed on 28/03/2015 at 19:14.
Pushed by hindenburg into branch 'master'.

Fix hang in exiting konsole with Ctrl+D with QInputMethodQuery

Add missing incrementation in for loop in decodeLine()

Thanks to Takahiro Hashimoto kenya888 gmail com for research, bug and
fix.
REIVEW: 123143

M  +2    -0    src/TerminalCharacterDecoder.cpp

http://commits.kde.org/konsole/7017a999d620562f7e51fd11303630bd0c4bf2ff
Comment 2 Kurt Hindenburg 2015-03-28 19:18:59 UTC
Git commit 154d58075922eddfc016e4156bc400d6ea24d39c by Kurt Hindenburg.
Committed on 28/03/2015 at 19:14.
Pushed by hindenburg into branch 'Applications/15.04'.

Fix hang in exiting konsole with Ctrl+D with QInputMethodQuery

Add missing incrementation in for loop in decodeLine()

Thanks to Takahiro Hashimoto kenya888 gmail com for research, bug and
fix.
REIVEW: 123143
(cherry picked from commit 7017a999d620562f7e51fd11303630bd0c4bf2ff)

M  +2    -0    src/TerminalCharacterDecoder.cpp

http://commits.kde.org/konsole/154d58075922eddfc016e4156bc400d6ea24d39c