Author Topic: Segmentation fault in nativeparser.cpp  (Read 21780 times)

Offline christobal

  • Multiple posting newcomer
  • *
  • Posts: 41
Segmentation fault in nativeparser.cpp
« on: February 12, 2013, 08:53:19 am »
This happens on line 1257, if the Code completion is configured to use one parser per project and the number of loaded projects exceeds the "Maximum allowed parsers" configuration.

This is how I encountered it:
- Configured CC to use one parser per project
- Set the number of max. allowed parsers to 2
- Loaded 2 projects to workspace -> OK
- Loaded 3rd project causes segmentation fault

I use Code::Blocks on Win7 (64-Bit) Rev. 8836; built with wxWidgets 2.8
With Code::Blocks 12.11 the behaviour is the same

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: Segmentation fault in nativeparser.cpp
« Reply #1 on: February 12, 2013, 09:10:57 am »
Do you have a backtrace?
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]

Offline christobal

  • Multiple posting newcomer
  • *
  • Posts: 41
Re: Segmentation fault in nativeparser.cpp
« Reply #2 on: February 12, 2013, 09:35:45 am »
Do you have a backtrace?

C::B didn't create a crash.log, but I have the call stack from the debugger

Code
#0 65EC347F	NativeParser::RemoveObsoleteParsers(this=0x56c5a60) (D:\codeblocks\source\src\plugins\codecompletion\nativeparser.cpp:1257)
#1 65EBE8A8 NativeParser::CreateParser(this=0x56c5a60, project=0xecb8f60) (D:\codeblocks\source\src\plugins\codecompletion\nativeparser.cpp:590)
#2 65EAB40C CodeCompletion::OnProjectActivated(this=0x56c5a18, event=...) (D:\codeblocks\source\src\plugins\codecompletion\codecompletion.cpp:2384)
#3 65F28428 cbEventFunctor<CodeCompletion, CodeBlocksEvent>::Call(this=0x5cb5028, event=...) (D:/codeblocks/source/src/include/cbfunctor.h:35)
#4 6189A918 Manager::ProcessEvent(this=0xd9a588, event=...) (D:\codeblocks\source\src\sdk\manager.cpp:179)
#5 618B07B6 PluginManager::NotifyPlugins(this=0x2eef4f8, event=...) (D:\codeblocks\source\src\sdk\pluginmanager.cpp:1445)
#6 618D06E9 ProjectManager::SetProject(this=0xdcb368, project=0xecb8f60, refresh=true) (D:\codeblocks\source\src\sdk\projectmanager.cpp:494)
#7 618D3ADF ProjectManager::LoadProject(this=0xdcb368, filename=..., activateIt=true) (D:\codeblocks\source\src\sdk\projectmanager.cpp:792)
#8 0044A064 MainFrame::DoOpenProject(this=0xdbca38, filename=..., addToHistory=true) (D:\codeblocks\source\src\src\main.cpp:1831)
#9 00449B2F MainFrame::OpenGeneric(this=0xdbca38, filename=..., addToHistory=true) (D:\codeblocks\source\src\src\main.cpp:1780)
#10 004524AF MainFrame::OnFileReopenProject(this=0xdbca38, event=...) (D:\codeblocks\source\src\src\main.cpp:2771)
#11 705C7670 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#12 705C77A9 wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#13 705C7B74 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#14 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#15 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#16 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#17 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#18 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#19 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#20 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#21 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#22 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#23 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#24 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#25 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#26 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#27 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#28 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#29 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)

BTW: The same happens if you have loaded a couple of projects and then reduce the number of max. parsers to a number less than currently opened projects.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #3 on: February 21, 2013, 03:41:14 pm »
Ok, Thanks.
Same crash here.
crash code:
Code
void NativeParser::RemoveObsoleteParsers()
{
    TRACE(_T("NativeParser::RemoveObsoleteParsers()"));

    ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
    const size_t maxParsers = cfg->ReadInt(_T("/max_parsers"), 5);
    wxArrayString removedProjectNames;
    std::pair<cbProject*, ParserBase*> info = GetParserInfoByCurrentEditor();

    while (m_ParserList.size() > maxParsers)
    {
        bool deleted = false;
        for (ParserList::const_iterator it = m_ParserList.begin(); it != m_ParserList.end(); ++it)
        {
            if (it->second == info.second)
                continue;

            if (DeleteParser(it->first))
            {
                wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
                removedProjectNames.Add(prj);
                deleted = true;
                break;
            }
        }

line: wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
the debug log is:
Quote
> p it

[debug]> p it
[debug]$1 = {first = , second = }
[debug]>>>>>>cb_gdb:

$1 = {first = , second = }
> p it->first

[debug]> p it->first
[debug]$2 = (cbProject *) 0xfeeefeee
[debug]>>>>>>cb_gdb:

$2 = (cbProject *) 0xfeeefeee
> p it->first->GetTitle()

[debug]> p it->first->GetTitle()
[debug]Cannot access memory at address 0xfeeefeee
[debug]>>>>>>cb_gdb:

Cannot access memory at address 0xfeeefeee

No time to analyze the bug. :)
It would better to file a bug report in BerliOS site, so it never be forgot.

BTW: which version of gdb did you use, it looks your gdb have longer backtrace them mine.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline jarod42

  • Multiple posting newcomer
  • *
  • Posts: 87
Re: Segmentation fault in nativeparser.cpp
« Reply #4 on: February 21, 2013, 04:42:26 pm »
I assume that DeleteParser modify m_ParserList, so the iterator 'it' is no longer valid.

Moving
Code
wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
just before
Code
if (DeleteParser(it->first))
should fix the issue.

Offline christobal

  • Multiple posting newcomer
  • *
  • Posts: 41
Re: Segmentation fault in nativeparser.cpp
« Reply #5 on: February 22, 2013, 08:26:55 am »
I assume that DeleteParser modify m_ParserList, so the iterator 'it' is no longer valid.

Moving
Code
wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
just before
Code
if (DeleteParser(it->first))
should fix the issue.

It does. CC seems to work as well for all opened projects.

@ollydbg: using GDB 7.2

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #6 on: February 26, 2013, 02:21:07 am »
I assume that DeleteParser modify m_ParserList, so the iterator 'it' is no longer valid.

Moving
Code
wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
just before
Code
if (DeleteParser(it->first))
should fix the issue.

You are right, I just review the logic of DeleteParser(), look below:
Code
bool NativeParser::DeleteParser(cbProject* project)
{
    wxString prj = (project ? project->GetTitle() : _T("*NONE*"));

    ParserList::iterator it = m_ParserList.begin();
    if (!m_ParserPerWorkspace)
    {
        for (; it != m_ParserList.end(); ++it)
        {
            if (it->first == project)
                break;
        }
    }

    if (it == m_ParserList.end())
    {
        CCLogger::Get()->DebugLog(F(_T("NativeParser::DeleteParser(): Parser does not exist for delete '%s'!"), prj.wx_str()));
        return false;
    }

    bool removeProjectFromParser = false;
    if (m_ParserPerWorkspace)
        removeProjectFromParser = RemoveProjectFromParser(project);

    if (m_ParsedProjects.empty())
    {
        if (it->second == m_Parser)
          SetParser(m_TempParser); // Also updates class browser

        wxString log(F(_("NativeParser::DeleteParser(): Deleting parser for project '%s'!"), prj.wx_str()));
        CCLogger::Get()->Log(log);
        CCLogger::Get()->DebugLog(log);

        delete it->second;
        m_ParserList.erase(it);

        return true;
    }

    if (removeProjectFromParser)
        return true;

    CCLogger::Get()->DebugLog(_T("NativeParser::DeleteParser(): Deleting parser failed!"));
    return false;
}

Here
Code
        m_ParserList.erase(it);
The element is removed.
But return from the function.
Code
it->first
The constant iterator is reused.

I'm going to fix it by your suggestion. Thanks.

It does. CC seems to work as well for all opened projects.
Thanks for the test.
Quote
@ollydbg: using GDB 7.2
Thanks, but I see that longer bt report are some redundant lines like:
Quote
#13 705C7B74   wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#14 705C7B10   wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#15 705C7B10   wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#16 705C7B10   wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
...
Newer GDB(I'm using GDB CVS head) just stop unwinding in this cases. :)
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #7 on: February 26, 2013, 02:33:27 am »
Fixed in rev 8856. Thanks for you contribution.
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline christobal

  • Multiple posting newcomer
  • *
  • Posts: 41
Re: Segmentation fault in nativeparser.cpp
« Reply #8 on: March 07, 2013, 08:30:35 am »
Thanks for fixing.

Unfortunally, I found another one in nativeparser.cpp...

This time it happens if you open a project and *immediately* close it. The problem occures in NativeParser::OnParserStart, which seems to recceive a cbProject pointer to a project that has already been deleted (project->GetTitle refers to 0xfeeefeee).

The Backtrace (C::B Rev 8900) is:

Code
#0 00000000	0xfeeefeee in ??() (??:??)
#1 65ECCBD3 NativeParser::OnParserStart(this=0x32bd5b0, event=...) (D:\projekte\codeblocks\source2\src\plugins\codecompletion\nativeparser.cpp:2458)
#2 705C7670 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#3 705C7A96 wxEvtHandler::SearchDynamicEventTable(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#4 705C7B4B wxEvtHandler::ProcessEvent(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#5 65EF4C49 Parser::ProcessParserEvent(this=0x11503218, state=ParserCommon::ptCreateParser, id=1391, info=...) (D:\projekte\codeblocks\source2\src\plugins\codecompletion\parser\parser.cpp:1178)
#6 65EF3449 Parser::OnBatchTimer(this=0x11503218, event=...) (D:\projekte\codeblocks\source2\src\plugins\codecompletion\parser\parser.cpp:1078)
#7 705C7670 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#8 705C7A96 wxEvtHandler::SearchDynamicEventTable(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#9 705C7B4B wxEvtHandler::ProcessEvent(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#10 706D70ED wxTimerBase::Notify() () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#11 70607BDC wxTimerWndProc() (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#12 75CC6238 USER32!IsDialogMessageW() (C:\Windows\syswow64\user32.dll:??)
#13 00000000 0x000309a8 in ??() (??:??)
#14 75CC68EA USER32!AllowForegroundActivation() (C:\Windows\syswow64\user32.dll:??)
#15 70607B64 wxProcessTimer(wxTimer&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#16 75CC7D31 USER32!GetMessageExtraInfo() (C:\Windows\syswow64\user32.dll:??)
#17 00000000 0x00000000 in ??() (??:??)




Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #9 on: March 07, 2013, 08:54:47 am »
Thanks for fixing.

Unfortunally, I found another one in nativeparser.cpp...

This time it happens if you open a project and *immediately* close it. The problem occures in NativeParser::OnParserStart, which seems to recceive a cbProject pointer to a project that has already been deleted (project->GetTitle refers to 0xfeeefeee).

The Backtrace (C::B Rev 8900) is:

Hi, many thanks for the bug report. I'm currently under heavy work load this week, so I will look into it next week.
The simple logic is: In the NativeParser, there is a Map to hold the database.
Code
cbProject*  -> Parser*
Each Parser is associated with one cbProject. (In another mode, if we use one parser for the whole workspaces, then there is only one parser for all the cbProjects in the workspaces)



If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #10 on: March 09, 2013, 04:38:57 pm »
I get similar crash, but not the same bt as yours.

Q:
Code
cbProject* ProjectManager::LoadProject(const wxString& filename, bool activateIt)
{
    cbProject* result = 0;
    if (!wxFileExists(filename) || !BeginLoadingProject())
    {
        return 0;
    }

    // "Try" block (loop which only gets executed once)
    // These blocks are extremely useful in constructs that need
    // premature exits. Instead of having multiple return points,
    // multiple return values and/or gotos,
    // you just break out of the loop (which only gets executed once) to exit.
    do
    {
        cbProject* project = IsOpen(filename);
        if (project)
        {
            // already open
            result = project;
            break;
        }

        if (FileTypeOf(filename) == ftCodeBlocksProject)
        {
            project = new cbProject(filename);

            // We need to do this because creating cbProject allows the app to be
            // closed in the middle of the operation. So the class destructor gets
            // called in the middle of a method call.

            if (!project->IsLoaded())
            {
                delete project;
                break;
            }

            result = project;
        }
        else // !ftCodeBlocksProject
        {
            // the plugin handler should call begin/end on its own...
            EndLoadingProject(0);

            cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
            if (plugin)
                plugin->OpenFile(filename);
        }

        break;
    }  while (false);
    // we 're done

    EndLoadingProject(result);
    if (activateIt)
    {
        if (m_IsLoadingWorkspace)
            // postpone the call to SetProject() until EndLoadingWorkspace() is called
            // (we must call RebuildTree() before SetProject() is called)
            m_pProjectToActivate = result;
        else
            SetProject(result, true);
    }

    return result;
}

I don't understand this comment.
Code
            // We need to do this because creating cbProject allows the app to be
            // closed in the middle of the operation. So the class destructor gets
            // called in the middle of a method call.

            if (!project->IsLoaded())
            {
                delete project;
                break;
            }
The project may be deleted when loading? I don't know how it did.
« Last Edit: March 09, 2013, 04:40:54 pm by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #11 on: March 16, 2013, 10:06:52 am »
Today, I try to reproduce this crash.

Firstly, I disable all the plugins except Codecompletion plugin, and I can't reproduce the crash
But after I enable the Compiler plugin, then I can reproduce the crash.

So, can anyone confirm this? Thanks.

In CC's code, it will call some compiler's function to get some include paths of GCC, maybe it is un-safe.

EDIT: Should the Compiler plugin be detached/destroyed after CC plugin?
« Last Edit: March 16, 2013, 10:19:00 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Jenna

  • Administrator
  • Lives here!
  • *****
  • Posts: 7252
Re: Segmentation fault in nativeparser.cpp
« Reply #12 on: March 16, 2013, 10:19:05 am »
Today, I try to reproduce this crash.

Firstly, I disable all the plugins except Codecompletion plugin, and I can't reproduce the crash
But after I enable the Compiler plugin, then I can reproduce the crash.

So, can anyone confirm this? Thanks.

In CC's code, it will call some compiler's function to get some include paths of GCC, maybe it is un-safe.

EDIT: Should the Compiler plugin should be detached after CC plugin?

There are other crash, that only occur when cc- and compiler-plugin are enabled (if I remember correctly).

If one plugin depends on another it's always unsafe, and we should have some kind of dependency and priority checking for the plugins, to force a load and unload-order.

But in my opinion no plugin should try to use other plugins funnctions before all plugins are loaded (that might not work, if some functions are used for initializing) and after unloading plugins has started.

This will not cover the problem of one plugin depending on another one in normal use.
So the dependency and priority approach might be better.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Segmentation fault in nativeparser.cpp
« Reply #13 on: March 16, 2013, 10:28:13 am »
Quote
There are other crash, that only occur when cc- and compiler-plugin are enabled (if I remember correctly).

If one plugin depends on another it's always unsafe, and we should have some kind of dependency and priority checking for the plugins, to force a load and unload-order.

But in my opinion no plugin should try to use other plugins funnctions before all plugins are loaded (that might not work, if some functions are used for initializing) and after unloading plugins has started.
The crash happens like below steps(I guess):
1, app started
2, both cc and compiler plugin loaded correctly
3, user open a cbp project
4, cc start parsing (after some timer delay) and query compiler search path from compiler plugin(this internally call gcc command line)
5, user click the "close" button of the app

Then, I guess compiler destroyed before cc, so crash happens.

Quote
This will not cover the problem of one plugin depending on another one in normal use.
So the dependency and priority approach might be better.
Yes, I think priority approach is good.
« Last Edit: March 16, 2013, 10:32:45 am by ollydbg »
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline oBFusCATed

  • Developer
  • Lives here!
  • *****
  • Posts: 13406
    • Travis build status
Re: Segmentation fault in nativeparser.cpp
« Reply #14 on: March 16, 2013, 04:43:59 pm »
Then, I guess compiler destroyed before cc, so crash happens.
Probably you can add an event which notifies all plugins that the unload process has started, so they can clean themselves and they can untangle some of the dependencies.
(most of the time I ignore long posts)
[strangers don't send me private messages, I'll ignore them; post a topic in the forum, but first read the rules!]