Menu

#1588 Crash in wxRecursionGuard in clangd_client

Next_Nightly
applied
pecan
None
Patch
2026-02-23
2026-02-23
pecan
No

clangd_client is using local variables and ProcessEvent from withing a thread.
It should be using cross-thread commnuication methods instead.
Forum thread:
https://forums.codeblocks.org/index.php/topic,26139.msg178428.html#msg178428

Discussion

  • pecan

    pecan - 2026-02-23

    Experimental patch

     

    Last edit: pecan 2026-02-23
  • pecan

    pecan - 2026-02-23

    Fix patch 1:

    Index: src/LSPclient/client.cpp

    --- src/LSPclient/client.cpp (revision 13794)
    +++ src/LSPclient/client.cpp (working copy)
    @@ -1,3 +1,4 @@
    +#include <memory>
    #include <ctime>
    #include <iomanip>
    #include <sstream>
    @@ -938,8 +939,8 @@
    void ProcessLanguageClient::OnClangd_stderr(wxThreadEvent& event)
    // ----------------------------------------------------------------------------
    {</sstream></iomanip></ctime></memory>

    • std::string* pErrStr = event.GetPayload<std::string*>();</std::string*>
    • if ( pErrStr->length())
    • std::shared_ptr<std::string> pErrStr = event.GetPayload<std::shared_ptr\<std::string>>();</std::shared_ptr\<std::string></std::string>
    • if ( pErrStr && pErrStr->length())
      writeServerLog( pErrStr->c_str() );

      return;
      @@ -981,12 +982,14 @@
      }

      // Append clangd incomming response data to buffer;

    • std::string* pRawOutput = event.GetPayload<std::string*>();</std::string*>

    • if (not pRawOutput->size())
    • std::shared_ptr<std::string> pRawOutput = event.GetPayload<std::shared_ptr\<std::string>>();</std::shared_ptr\<std::string></std::string>
    • if (not pRawOutput || not pRawOutput->size())
      {
      writeClientLog("Error: clangd responded with a zero length buffer.");
    • m_MutexInputBufGuard.Unlock();
    • return;
      }
    • std::string std_clangdRawOutput = *pRawOutput;
    • //std::string std_clangdRawOutput = pRawOutput;
      m_std_LSP_IncomingStr.append(
      pRawOutput);
      m_CondInputBuf.Signal(); //(Christo ticket 1423 2023/10/16) post jsonRead wait

    Index: src/unixprocess/asyncprocess/UnixProcess.cpp

    --- src/unixprocess/asyncprocess/UnixProcess.cpp (revision 13794)
    +++ src/unixprocess/asyncprocess/UnixProcess.cpp (working copy)
    @@ -20,6 +20,7 @@
    #include <string.h>
    #include <sys select.h="">
    #include <sys types.h="">
    +#include <memory></memory></sys></sys></string.h>

    #include <wx msgdlg.h=""></wx>

    @@ -226,9 +227,14 @@
    process->m_owner->ProcessEvent(evt);
    break;
    } else if(not content.empty()) {

    • wxThreadEvent evt(isReadFromFdOut ? wxEVT_ASYNC_PROCESS_OUTPUT : wxEVT_ASYNC_PROCESS_STDERR);
    • evt.SetPayload<std::string*>(&content);</std::string*>
    • process->m_owner->ProcessEvent(evt);
    • //wxThreadEvent evt(isReadFromFdOut ? wxEVT_ASYNC_PROCESS_OUTPUT : wxEVT_ASYNC_PROCESS_STDERR);
    • //evt.SetPayload<std::string*>(&content);</std::string*>
    • //process->m_owner->ProcessEvent(evt);
    • wxThreadEvent* evt = new wxThreadEvent(isReadFromFdOut ? wxEVT_ASYNC_PROCESS_OUTPUT : wxEVT_ASYNC_PROCESS_STDERR);
    • evt->SetPayload(std::make_shared<std::string>(content));</std::string>
    • process->m_owner->QueueEvent(evt);
    •              content.clear();
               }
           }
      

      Index: src/winprocess/asyncprocess/processreaderthread.cpp

      --- src/winprocess/asyncprocess/processreaderthread.cpp (revision 13794)
      +++ src/winprocess/asyncprocess/processreaderthread.cpp (working copy)
      @@ -9,6 +9,7 @@
      // (at your option) any later version.
      //
      // ----------------------------------------------------------------------------
      +#include <memory>
      #include "asyncprocess.h"
      #include "processreaderthread.h"</memory>

    @@ -75,7 +76,7 @@
    // fallback to the event system
    // we got some data, send event to parent
    //clProcessEvent e(wxEVT_ASYNC_PROCESS_OUTPUT);

    • wxThreadEvent e(wxEVT_ASYNC_PROCESS_OUTPUT, wxID_NONE);
    • wxThreadEvent* e = new wxThreadEvent(wxEVT_ASYNC_PROCESS_OUTPUT, wxID_NONE);
      //-wxString& b = const_cast<wxstring&>(e.GetOutput());
      //-b.swap(buff);
      //e.SetProcess(m_process);
      @@ -86,13 +87,13 @@
      #else
      std::string stdstr = buff.ToStdString(wxConvUTF8);
      #endif</wxstring&>
    • e.SetPayload<std::string*>(&stdstr);</std::string*>
    • m_notifiedWindow->ProcessEvent(e);
    • e->SetPayload(std::make_shared<std::string>(stdstr));</std::string>
    • m_notifiedWindow->QueueEvent(e);
      }
      if(!buffErr.IsEmpty() && m_notifiedWindow) {
      // we got some data, send event to parent
      //clProcessEvent e(wxEVT_ASYNC_PROCESS_STDERR);
    • wxThreadEvent e(wxEVT_ASYNC_PROCESS_STDERR, wxID_NONE);
    • wxThreadEvent* e = new wxThreadEvent(wxEVT_ASYNC_PROCESS_STDERR, wxID_NONE);
      //wxString& b = const_cast<wxstring&>(e.GetOutput());
      //b.swap(buffErr);
      //e.SetProcess(m_process);
      @@ -99,12 +100,12 @@
      //m_notifiedWindow->AddPendingEvent(e);
      //-std::string stdstr = buffErr.ToStdString(); loses data
      #if wxCHECK_VERSION(3,1,5)</wxstring&>
    • std::string stdstr = buff.utf8_string();
    • std::string stdstr = buffErr.utf8_string();
      #else
    • std::string stdstr = buff.ToStdString(wxConvUTF8);
    • std::string stdstr = buffErr.ToStdString(wxConvUTF8);
      #endif
    • e.SetPayload<std::string*>(&stdstr);</std::string*>
    • m_notifiedWindow->ProcessEvent(e);
    • e->SetPayload(std::make_shared<std::string>(stdstr));</std::string>
    • m_notifiedWindow->QueueEvent(e);
      }
      }
      }
     
  • pecan

    pecan - 2026-02-23

    Fixed svn 13797, thanks ollydbg

     
  • pecan

    pecan - 2026-02-23
    • status: pending --> applied
    • Type: Undefined --> Patch
    • Milestone: Undefined --> Next_Nightly
     

Log in to post a comment.

MongoDB Logo MongoDB