microsoft / vscode-cpptools

Official repository for the Microsoft C/C++ extension for VS Code.
Other
5.52k stars 1.55k forks source link

Crash in query_include_path_suggestions_impl #12554

Closed Kracken256 closed 1 month ago

Kracken256 commented 2 months ago

Environment

Bug Summary and Steps to Reproduce

Bug Summary: Language server crashing (SEGSEV) on moderately large project. My project makes extensive use of C++ macros, templates, and abstractions in general. The source code of my project is GitHub Repo

Steps to reproduce:

  1. Use the VSCode as normal
  2. Language server keeps randomly crashing on my project (20+ times in 10 minutes).

Expected behavior:

  1. Not to crash / not to segfault

Configuration and Logs

{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/libquix-core/include",
                "${workspaceFolder}/libquix-lexer/include",
                "${workspaceFolder}/libquix-parser/include",
                "${workspaceFolder}/libquix-parser/src",
                "${workspaceFolder}/libquix-qxir/include",
                "${workspaceFolder}/libquix-qxir/src",
                "${workspaceFolder}/qpkg/src"
            ],
            "defines": [],
            "cStandard": "c23",
            "cppStandard": "c++20",
            "intelliSenseMode": "linux-gcc-x64"
        }
    ],
    "version": 4
}

/// ==============================================================================
/// CALL TRACE
/// ==============================================================================

A C/C++ extension process has crashed. The crashing process name, date/time, signal, and call stack are below -- it would be helpful to include that in a bug report at https://github.com/Microsoft/vscode-cpptools/issues.

cpptools
8/8/2024, 10:53:52 AM
SIGSEGV
browse_engine::query_include_path_suggestions_impl(std::string const&, std::set<std::string, std::less<std::string>>&, bool, std::map<code_store::record_id_t<code_store::file_tag_t>, std::string, std::less<code_store::record_id_t<code_store::file_tag_t>>, std::allocator<std::pair<code_store::record_id_t<code_store::file_tag_t> const, std::string>>>*)+290
browse_engine::query_include_path_suggestions(std::string const&, std::map<code_store::record_id_t<code_store::file_tag_t>, std::string, std::less<code_store::record_id_t<code_store::file_tag_t>>, std::allocator<std::pair<code_store::record_id_t<code_store::file_tag_t> const, std::string>>>&)+84
browse_engine::parse_file(std::shared_ptr<workspace_folder_context> const&, char const*, code_store::record_id_t<code_store::file_tag_t> const&, std::unordered_set<code_store::record_id_t<code_store::file_tag_t>, std::hash<code_store::record_id_t<code_store::file_tag_t>>, std::equal_to<code_store::record_id_t<code_store::file_tag_t>>, std::allocator<code_store::record_id_t<code_store::file_tag_t>>>&, std::string const&, std::set<std::string, std::less<std::string>> const&, parser&, std::function<void (msvc::result_t)>&&, std::shared_ptr<browse_include_paths> const&, bool)+4617
browse_engine::parse_file(std::shared_ptr<workspace_folder_context> const&, char const*, bool, std::function<void (msvc::result_t)>&&, std::shared_ptr<browse_include_paths> const&, bool)+1201
cpptools_context::handle_parse_file(cpptools_context::file_and_task_token&&)+835
msvc::thread_manager_t::queue_item<msvc::deque_thread<cpptools_context::file_and_task_token>::defer(cpptools_context::file_and_task_token&&)::{lambda()#1}>::operator()()+340
msvc::thread_manager_t::do_work(unsigned int)+486

Other Extensions

  1. GitHub copilot
  2. C++ Themes

Additional context

The full debug log cxx-log.txt

sean-mcmanus commented 2 months ago

@Kracken256 I haven't been able to repro this (and I'm not sure how that particular crash call stack location could be crashing). Do you repro this with a clean git clone of that repo? Does it require boost to be installed? Do you know what version of boost?

Do you have the file libquix-qxir/tests/example.cc? Does it always crash when that file is changed?

Kracken256 commented 2 months ago

It does not require boost to crash. These crashes have been happening before I added boost to my project. Earlier today I purged vscode (the snap package) and deleted the $HOME/.config/Code and $HOME/.vscode directories. I reinstalled vscode via snap, reinstalled the c++ extension pack. Opened my project and within a minute it started crashing again.

Kracken256 commented 2 months ago

The example.cc file was ten trivial lines of c++.

something like

include

int main() { init_lib(); // a few comments deinit_lib(); }

Kracken256 commented 2 months ago

It always crashes within a minute of editing or including a c++ header over ~1000 loc (typically recursively has to include others, too). This extends to any source file, irrespective of size, that includes such a header file.

sean-mcmanus commented 2 months ago

@Kracken256 Where is quix-lib.h from?

Kracken256 commented 2 months ago

I mean libquix-qxir/include/quix-qxir/Lib.h

at

https://github.com/Kracken256/quix/blob/main/libquix-qxir/include/quix-qxir/Lib.h

Yingzi1234 commented 2 months ago

@Kracken256 @sean-mcmanus We cannot reproduced this issue on latest C/C++ version v1.21.6, you can get the details below. Please let me know if you have any concerns! Thank you! ENV:

  1. Linux: 22.04 4LTS
  2. VSCode version: 1.92.0
  3. C/C++ version: v1.21.6

Repro steps:

  1. Open VSCode and clone this repo GitHub Repo
  2. Open libquix-qxir/include/quix-qxir/Lib.h file
  3. Edit some content and save it
  4. Checking the output window (C/C++) for crashes

Actual result: No crashes in the output window (C/C++) 12554

sean-mcmanus commented 2 months ago

@Kracken256 As was previously mentioned, our team isn't able to reproduce the issue, and we are not aware of other users hitting this crash. Can you think of anything unusual about your setup that could be required in order to trigger it? The code involved in the crash call stack is doing a database query to find potential matching files for a #include statement in a file.

Kracken256 commented 2 months ago

There does not seem to be anything special about my setup. I'm using Linux Mint with the VSCode snap package.

A few more notes:

  1. My project is using quite a few macros including #include guards that in certain cases result in a cyclic dependency graph. However, when the code is actually compiled #defines's prevent this from happening and it is okay. It may be possible that cpptools (or whatever is actually used for parsing) is unable to see this while iterating over the source code. This could maybe lead to a stack overflow or something idk.
  2. I use a custom build system for this project that uses Docker to build the code. This build system modifies the ${projectDir}/bin and ${projectDir}/build directories. These directories are quite large (tens of MBs). Maybe VSCode is being overloaded while trying to track/watch those directories? My computer has 64 GB of RAM and an intel i9 CPU, so resources shouldn't be an issue.
  3. The build directory created with my custom build system maybe contain files with non-user permissions (docker runs as root). Maybe VSCode forgets to check if opening a file fails due to permissions?
  4. I was able to reproduce the exact same issue in my Kali Linux VM (basically a fresh install of Kali 2024).
  5. At this point the c/c++ language server crashes every 15-20 seconds (literally). It is unbearable to the point that I am now trying to learn NEOVIM.
  6. I very frequently format, save, and switch files. This shouldn't be an issue, but maybe?
  7. My code uses many instances of templates and macros.
  8. The window crashes much more often, but not only, when editing some (most) template methods where I am trying to get type inference on an incomplete line of code. I'll attach an example of something that will very likely crash my editor while editing.
  9. Basically, it just feels like when writing any non-trivial c++20 the editor crashes 80% of the time within 1 minute (not actually measured, but this is for sure a conservative estimate).

Example of some of my code that crashes. This code is not usable on its own because it depends on many other symbols from the project.


qxir::Expr *qconv_lower_binexpr(ConvState &s, qxir::Expr *lhs, qxir::Expr *rhs, qlex_op_t op) {
#define STD_BINOP(op) qxir::create<qxir::BinExpr>(lhs, rhs, qxir::Op::op)
#define ASSIGN_BINOP(op)                                                                \
  qxir::create<qxir::BinExpr>(lhs, qxir::create<qxir::BinExpr>(lhs, rhs, qxir::Op::op), \
                              qxir::Op::Set)

  switch (op) {
    case qOpPlus: {
      return STD_BINOP(Plus);
    }
    case qOpMinus: {
      return STD_BINOP(Minus);
    }
    case qOpTimes: {
      return STD_BINOP(Times);
    }
    case qOpSlash: {
      return STD_BINOP(Slash);
    }
    case qOpPercent: {
      return STD_BINOP(Percent);
    }
    case qOpBitAnd: {
      return STD_BINOP(BitAnd);
    }
    case qOpBitOr: {
      return STD_BINOP(BitOr);
    }
    case qOpBitXor: {
      return STD_BINOP(BitXor);
    }
    case qOpBitNot: {
      return STD_BINOP(BitNot);
    }
    case qOpLogicAnd: {
      return STD_BINOP(LogicAnd);
    }
    case qOpLogicOr: {
      return STD_BINOP(LogicOr);
    }
    case qOpLogicXor: {
      // A ^^ B == (A || B) && !(A && B)
      auto a = qxir::create<qxir::BinExpr>(lhs, rhs, qxir::Op::LogicOr);
      auto b = qxir::create<qxir::BinExpr>(lhs, rhs, qxir::Op::LogicAnd);
      auto not_b = qxir::create<qxir::UnExpr>(b, qxir::Op::LogicNot);
      return qxir::create<qxir::BinExpr>(a, not_b, qxir::Op::LogicAnd);
    }
    case qOpLogicNot: {
      return STD_BINOP(LogicNot);
    }
    case qOpLShift: {
      return STD_BINOP(LShift);
    }
    case qOpRShift: {
      return STD_BINOP(RShift);
    }
    case qOpROTR: {
      return STD_BINOP(ROTR);
    }
    case qOpROTL: {
      return STD_BINOP(ROTL);
    }
    case qOpInc: {
      return STD_BINOP(Inc);
    }
    case qOpDec: {
      return STD_BINOP(Dec);
    }
    case qOpSet: {
      return STD_BINOP(Set);
    }
    case qOpPlusSet: {
      return ASSIGN_BINOP(Plus);
    }
    case qOpMinusSet: {
      return ASSIGN_BINOP(Minus);
    }
    case qOpTimesSet: {
      return ASSIGN_BINOP(Times);
    }
    case qOpSlashSet: {
      return ASSIGN_BINOP(Slash);
    }
    case qOpPercentSet: {
      return ASSIGN_BINOP(Percent);
    }
    case qOpBitAndSet: {
      return ASSIGN_BINOP(BitAnd);
    }
    case qOpBitOrSet: {
      return ASSIGN_BINOP(BitOr);
    }
    case qOpBitXorSet: {
      return ASSIGN_BINOP(BitXor);
    }
    case qOpLogicAndSet: {
      return ASSIGN_BINOP(LogicAnd);
    }
    case qOpLogicOrSet: {
      return ASSIGN_BINOP(LogicOr);
    }
    case qOpLogicXorSet: {
      // a ^^= b == a = (a || b) && !(a && b)

      auto a = qxir::create<qxir::BinExpr>(lhs, rhs, qxir::Op::LogicOr);
      auto b = qxir::create<qxir::BinExpr>(lhs, rhs, qxir::Op::LogicAnd);
      auto not_b = qxir::create<qxir::UnExpr>(b, qxir::Op::LogicNot);
      return qxir::create<qxir::BinExpr>(
          lhs, qxir::create<qxir::BinExpr>(a, not_b, qxir::Op::LogicAnd), qxir::Op::Set);
    }
    case qOpLShiftSet: {
      return ASSIGN_BINOP(LShift);
    }
    case qOpRShiftSet: {
      return ASSIGN_BINOP(RShift);
    }
    case qOpROTRSet: {
      return ASSIGN_BINOP(ROTR);
    }
    case qOpROTLSet: {
      return ASSIGN_BINOP(ROTL);
    }
    case qOpLT: {
      return STD_BINOP(LT);
    }
    case qOpGT: {
      return STD_BINOP(GT);
    }
    case qOpLE: {
      return STD_BINOP(LE);
    }
    case qOpGE: {
      return STD_BINOP(GE);
    }
    case qOpEq: {
      return STD_BINOP(Eq);
    }
    case qOpNE: {
      return STD_BINOP(NE);
    }
    case qOpAs: {
      return STD_BINOP(CastAs);
    }
    case qOpIs: {
      auto fn = qxir::create<qxir::Ident>("__is");
      return qxir::create<qxir::Call>(fn, qxir::CallArgs({lhs, rhs}));
    }
    case qOpIn: {
      auto methname = qxir::create<qxir::String>("has");
      auto method = qxir::create<qxir::Index>(rhs, methname);
      return qxir::create<qxir::Call>(method, qxir::CallArgs({lhs}));
    }
    case qOpRange: {
      /// TODO:
      throw QError();
    }
    case qOpBitcastAs: {
      return STD_BINOP(BitcastAs);
    }
    default: {
      throw QError();
    }
  }
}
daniel-brosche commented 2 months ago

I have also this issue since some weeks.

cpptools
8/22/2024, 3:51:00 PM
SIGSEGV
code_analysis::process_async::cleanup() const+767
code_analysis::process_async::main()+1419
code_analysis::process_async_work(unsigned int, file_uri const&, std::optional<file_uri>&&, std::shared_ptr<workspace_folder_context> const&, std::shared_ptr<intellisense_client_config> const&)+103
msvc::thread_manager_t::do_work(unsigned int)+486

With the same setup I had no troubles approx. two weeks before.

sean-mcmanus commented 2 months ago

@daniel-brosche Your issue is different. I've moved it to https://github.com/microsoft/vscode-cpptools/issues/12615

Kracken256 commented 2 months ago

I have recently started using VSCode Online. I have not experienced any issues or crashes while editing my project online via VSCode Online.

The issue might be in the VSCode package present on the Snap store or some other issue.

Kracken256 commented 1 month ago

Hi @sean-mcmanus!

Any updates?

I recently did a fresh install. Same issue happened. This time I used the .deb package instead of snap.

Thanks

Kracken256 commented 1 month ago

I solved the issue.

  1. Uninstall the Microsoft C/C++ extension pack.
  2. Install the VSCode Clangd language server.
  3. Works perfectly 👌. Also clangd is like 5x faster somehow.