Bug 320875

Summary: Stackoverflkow in cmake parser
Product: [Applications] kdevelop Reporter: Sergey Vidyuk <sir.vestnik>
Component: Build tools: CMakeAssignee: kdevelop-bugs-null
Status: RESOLVED FIXED    
Severity: normal CC: aleixpol
Priority: NOR    
Version: git master   
Target Milestone: 4.3.0   
Platform: Arch Linux   
OS: Linux   
Latest Commit: Version Fixed In:
Sentry Crash Report:

Description Sergey Vidyuk 2013-06-07 19:39:54 UTC
kdevplatform git master revision: 4b80176fe175e4636f25107f597d95b9420379ea
kdevelop git master revision: 2af23e46ba1ec6cd2c003dae820f34f7b8e1464b

Projects opened:
https://gitorious.org/mahjong-night/qremotesignal
https://gitorious.org/mahjong-night/mahjong-night

fails for me after several minutes (no editing done at all). There were no such issue before rebuilding fresh master today (previous version was build earlier this week)

Stacktrace is deepper then 10000 frames consist of repeating walk/visit calls:
#0  QMutexLocker::QMutexLocker (this=0x7ffee67fc030, m=0x27e92f0) at /usr/include/qt4/QtCore/qmutex.h:109
#1  0x00007ffff010d020 in KDevelop::PersistentSymbolTable::getDeclarations (
    this=this@entry=0x7ffff044a4e0 <KDevelop::PersistentSymbolTable::self()::ret>, id=...) at ../../language/duchain/persistentsymboltable.cpp:312
#2  0x00007ffff010d2f2 in KDevelop::PersistentSymbolTable::getFilteredDeclarations (
    this=0x7ffff044a4e0 <KDevelop::PersistentSymbolTable::self()::ret>, id=..., visibility=...) at ../../language/duchain/persistentsymboltable.cpp:273
#3  0x00007ffff00b8a96 in KDevelop::TopDUContext::FindDeclarationsAcceptor::operator() (this=this@entry=0x7ffee67ffdb0, id=...)
    at ../../language/duchain/topducontext.cpp:812
#4  0x00007ffff00b92e5 in KDevelop::TopDUContext::applyAliases<KDevelop::TopDUContext::FindDeclarationsAcceptor> (this=this@entry=0x7fff280296c0, 
    previous=..., identifier=..., accept=..., position=..., canBeNamespace=canBeNamespace@entry=false, buddy=buddy@entry=0x0, 
    recursionDepth=recursionDepth@entry=0) at ../../language/duchain/topducontext.cpp:990
#5  0x00007ffff00b97bd in KDevelop::TopDUContext::applyAliases<KDevelop::TopDUContext::FindDeclarationsAcceptor> (this=this@entry=0x7fff280296c0, 
    identifiers=..., acceptor=..., position=..., canBeNamespace=canBeNamespace@entry=false) at ../../language/duchain/topducontext.cpp:1065
#6  0x00007ffff00b1c68 in KDevelop::TopDUContext::findDeclarationsInternal (this=this@entry=0x7fff280296c0, identifiers=..., position=..., 
    dataType=..., ret=..., flags=...) at ../../language/duchain/topducontext.cpp:873
#7  0x00007ffff00a0461 in KDevelop::DUContext::findDeclarations (this=0x7fff280296c0, identifier=..., position=..., topContext=topContext@entry=0x0, 
    flags=...) at ../../language/duchain/ducontext.cpp:1195
#8  0x00007fff486de075 in CMakeProjectVisitor::createUses (this=this@entry=0x7ffee6ffa890, desc=...)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2401
#9  0x00007fff486e9853 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=line@entry=1, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2306
#10 0x00007fff486ec87f in CMakeProjectVisitor::visit (this=0x7ffee6ffa890, call=0x7ffedd9c9080)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:1265
#11 0x00007fff486e9c51 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=line@entry=10, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2333
#12 0x00007fff486eee42 in CMakeProjectVisitor::visit (this=0x7ffee6ffa890, ifast=0x7ffedd9c7b10)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:1387
#13 0x00007fff486e9c51 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=9, line@entry=1, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2333
#14 0x00007fff486ec87f in CMakeProjectVisitor::visit (this=0x7ffee6ffa890, call=0x7ffedd9c8c70)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:1265
---Type <return> to continue, or q <return> to quit---
#15 0x00007fff486e9c51 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=18, line@entry=14, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2333
#16 0x00007fff486eee42 in CMakeProjectVisitor::visit (this=0x7ffee6ffa890, ifast=0x7ffedd9c6cc0)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:1387
#17 0x00007fff486e9c51 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=13, line@entry=1, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2333
#18 0x00007fff486ec87f in CMakeProjectVisitor::visit (this=0x7ffee6ffa890, call=0x7ffedd9c74d0)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:1265
#19 0x00007fff486e9c51 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=18, line@entry=14, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2333
#20 0x00007fff486eee42 in CMakeProjectVisitor::visit (this=0x7ffee6ffa890, ifast=0x7ffedd9c45f0)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:1387
#21 0x00007fff486e9c51 in CMakeProjectVisitor::walk (this=this@entry=0x7ffee6ffa890, fc=..., line=13, line@entry=1, isClean=isClean@entry=false)
    at ../../projectmanagers/cmake/parser/cmakeprojectvisitor.cpp:2333
...

Reproducible: Always
Comment 1 Aleix Pol 2013-06-10 18:50:01 UTC
Hi, I couldn't reproduce, can you maybe try with master?
Comment 2 Sergey Vidyuk 2013-06-13 18:04:51 UTC
Still facing this issue on the fresh git master
kdevplatform: 85b3cddb199947fe6fd774e5aa21da8de430d270
kdevelop: 6235adc8df55b9ff32dc7b22b8e3b144df35935f
Comment 3 Sergey Vidyuk 2013-06-13 18:25:41 UTC
http://pastebin.com/4c6yBgBZ cmake support debug logs
Comment 4 Aleix Pol 2013-06-17 00:30:12 UTC
Maybe try to nuke your sessions' ~/.cache/kdevduchain/<session>?

I don't see why it would crash...
Comment 5 Sergey Vidyuk 2013-06-18 18:27:32 UTC
Finflly find an evening for investigation. I've implemented simple frame storrage for cmake visitor and limited frame depth by 30 with printing stack on overflow. After then I've discovered the following cmake "stack overflow" in kdevelop cmake parser:

==> 0 "/home/vestnik/Development/Mahjong-Night/mahjong-night/CMakeLists.txt" 
==> 1 "find_package(Qt4)" 
==> 2 "/usr/share/cmake-2.8/Modules/FindQt4.cmake" 
==> 3 "130: _qt4_find_qmake(qmake;qmake4;qmake-qt4;qmake-mac, QT_QMAKE_EXECUTABLE, QTVERSION)" 
==> 4 "18: _qt4_find_qmake(qmake4;qmake-qt4;qmake-mac, QMAKE, QTVERSION)" 
==> 5 "18: _qt4_find_qmake(qmake-qt4;qmake-mac, QMAKE, QTVERSION)" 
==> 6 "18: _qt4_find_qmake(qmake-mac, QMAKE, QTVERSION)" 
==> 7 "18: _qt4_find_qmake(, QMAKE, QTVERSION)" 
==> 8 "18: _qt4_find_qmake(, QMAKE, QTVERSION)" 
==> 9 "18: _qt4_find_qmake(, QMAKE, QTVERSION)"
...

The begging of the _qt4_find_qmake contains the fillowing code:

  function(_QT4_FIND_QMAKE QMAKE_NAMES QMAKE_RESULT VERSION_RESULT)
    list(LENGTH QMAKE_NAMES QMAKE_NAMES_LEN)
    if(${QMAKE_NAMES_LEN} EQUAL 0)
      return()
    endif()
    ...
    list(REMOVE_AT QMAKE_NAMES 0)
    _qt4_find_qmake("${QMAKE_NAMES}" QMAKE QTVERSION)
    ...
  endfunction()

However there is no visit function for ReturnAst in CMakeProjectVisitor and it leads to the crach from this bug. I don't know yet why kdevelop finds only Qt5 qmake and will try to check if cmake have the same behaviour. If there will be more differencies between cmake and Kdevelop parser related to the _qt4_find_qmake I'll write about it in this bug.
Comment 6 Sergey Vidyuk 2013-06-19 16:36:07 UTC
Steps to reproduce:
 * System with only Qt4 installed
 * CMake based project using find_package(Qt4) call
 * QT_QMAKE_EXECUTABLE=/usr/bin/qmake in the build directory cache
 * Update wich brings Qt5 and makes "/usr/bin/qmake -query QT_VERSION" return 5.x.x
 * Open this project in KDevelop, wait for a bit.
 * KDevelop crashes

There are several issues leading to this crash:
 1 _qt4_find_qmake is recursive function using return cmake statement to stop recursion. However KDevelop cmake visitor does not handle return statement.
 2 _qt4_find_qmake uses set(...FORCE..) to reset cache variable and retry find_program on next iteration. However KDevelop do not handle forced cache var set properly in cmake visitor.
 3 _qt4_find_qmake sets QT_QMAKE_EXECUTABLE to NOTFOUND in order to retry find_program on next iteration. Kdevelopdo not retry program search if result var is set to NOTFOUND. However Kdevelop works correcly according to the cmake documentation and cmake doing parsing this macro wrong :)

In order to elliminate the crash it's enough to rerun cmake in the build directory after upgrade bringing Qt5. However I think that 1st and 2nd issues should be fixed. It's better to see some error message instead of segfault in this situation.
Comment 7 Sergey Vidyuk 2013-06-19 17:48:37 UTC
Fix for issue 2 from previous comment
https://git.reviewboard.kde.org/r/111133/
Fix for issue 1 from previous comment
https://git.reviewboard.kde.org/r/111135/
Comment 8 Aleix Pol 2013-06-19 23:55:22 UTC
Git commit 6435b362cde019a724d0e47482afaefeab941a86 by Aleix Pol, on behalf of Sergey Vidyuk.
Committed on 19/06/2013 at 17:32.
Pushed by apol into branch '4.5'.

Support return statement

REVIEW: 111135

M  +8    -3    projectmanagers/cmake/parser/cmakeprojectvisitor.cpp
M  +1    -0    projectmanagers/cmake/parser/cmakeprojectvisitor.h

http://commits.kde.org/kdevelop/6435b362cde019a724d0e47482afaefeab941a86
Comment 9 Aleix Pol 2013-06-19 23:55:58 UTC
Git commit c5593f565360e247371070afea2abf6543b4a172 by Aleix Pol, on behalf of Sergey Vidyuk.
Committed on 19/06/2013 at 17:32.
Pushed by apol into branch 'master'.

Support return statement

REVIEW: 111135

M  +8    -3    projectmanagers/cmake/parser/cmakeprojectvisitor.cpp
M  +1    -0    projectmanagers/cmake/parser/cmakeprojectvisitor.h

http://commits.kde.org/kdevelop/c5593f565360e247371070afea2abf6543b4a172