emacs-lsp / emacs-ccls

Emacs client for ccls, a C/C++ language server
200 stars 29 forks source link

ccls server dissconnects immediately #62

Closed JAGF009 closed 4 years ago

JAGF009 commented 4 years ago

Hello @MaskRay ,

I'm trying to use this package and I'm having quite some trouble to get it working right.

I've set up this small test project:

root
│   CMakeLists.txt
│   main.cpp
└───include
        hello.hpp

The problem that I'm facing is that whenever I go into the project in Emacs, a session starts and lpc-mode seems to be able to connect to the ccls server. But then, seconds after that the server closes the connection and lsp-mode prompts me to restart it, which ends up in a loop. The biggest amount of information that I've got is something related to error 116, but again this was with a Release build.

I generated a compile_commands.json file using this VS extension, and added a simple .ccls file to the root directory, although I think these have nothing to do with the issue, it was already happening without those files.

I feel like I'm missing something simple, but I can't find much information online.

For the system information, Im running windows 10 64 bits.

I've built LLVM and Clang from source (master) using MVS2017.

PS D:\llvm-project> git rev-parse head
4e9778e346f27b09724f39f92b34dd7336c2147a

PS> clang --version
clang version 10.0.0
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:\LLVM\bin

The commit from which I built ccls (also using MVS2017) is:

PS> git rev-parse head
bfac2162eb6931e09a64fd27e8356872b286d977

And my emacs configuration regarding ccls is, which I believe is pretty much the default one:

(use-package lsp-mode :commands lsp)
(use-package lsp-ui :commands lsp-ui-mode)
(use-package company-lsp :commands company-lsp)
(use-package helm-lsp :commands helm-lsp-workspace-symbol)
(use-package lsp-treemacs :commands lsp-treemacs-errors-list)

(use-package ccls
  :hook ((c-mode c++-mode objc-mode cuda-mode) .
     (lambda () (require 'ccls)(lsp))))

(setq cll/ccls-executable "C:/Program Files (x86)/ccls/bin/ccls.exe")
(setq cll/ccls-args '("--log-file=C:/Users/Jose/ccls.log" "--log-file-append=true" "--v=2"))
(setq ccls-executable cll/ccls-executable)
(setq ccls-args cll/ccls-args)

Thank you.

MaskRay commented 4 years ago

https://github.com/MaskRay/ccls/wiki/Debugging

Can you do some sanity check of the build, e.g. C:/Program\ Files\ (x86)/ccls/bin/ccls.exe --version

In a project root with either compile_commands.json or .ccls: C:/Program\ Files\ (x86)/ccls/bin/ccls.exe --index=. --log-file=C:/Users/Jose/ccls.log -v 2

JAGF009 commented 4 years ago

Sure!

PS> ccls --version
ccls version <unknown>
clang version 10.0.0 (https://github.com/llvm/llvm-project.git 4e9778e346f27b09724f39f92b34dd7336c2147a)
PS Basic> ccls.exe --index=. --log-file=ccls.log -v 2
entries:     1
pending:     0

The output log of this command is quite long, I pasted it here. The project is now as follows

root
│   .ccls
│   CMakeLists.txt
│   main.cpp
└───include
        mylib.hpp

I'm not sure it's useful but, the contents of .ccls are:

clang
%cpp -std=c++14
-Iinclude
MaskRay commented 4 years ago

If ccls.exe --index=. --log-file=ccls.log -v 2 works in the project root, this cannot be a ccls problem.

I am not sure spaces in ccls-executable are accepted on Windows. Can you place the directory in the PATH environment variable and use just ccls or ccls.exe?

JAGF009 commented 4 years ago

I set the ccls executable in the PATH and remove the log file argument. The emacs configuration is now:

(setq cll/ccls-executable "ccls.exe")
(setq cll/ccls-args '("--v=2"))
(setq ccls-executable cll/ccls-executable)
(setq ccls-args cll/ccls-args)

The same error happens and this are the contents of the ccls::stderr buffer, if it is useful this is the content of the lsp-log buffer.

Also this are the messages that I am getting when entering a cpp file

LSP :: Connected to [ccls:7388 status:starting].
LSP :: ccls:7388 initialized successfully
LSP :: ccls has exited (exited abnormally with code 116)
Server ccls:7388 exited with status exit. Do you want to restart it? (y or n) y
LSP :: Restarting LSP in buffer main.cpp
LSP :: Connected to [ccls:17452 status:starting].
LSP :: ccls:17452 initialized successfully
LSP :: ccls has exited (exited abnormally with code 116)
Server ccls:17452 exited with status exit. Do you want to restart it? (y or n) n
MaskRay commented 4 years ago

https://github.com/emacs-lsp/lsp-mode#troubleshooting

Can you try lsp-log-io?

JAGF009 commented 4 years ago

At this point I have to admit that I have pretty much no idea what I'm looking at, this looks like a normal server-client conversation to me I don't see any errors or disconnections or timeouts :/

Anyway here is the log if you want to take a loot at it, I feel like I'm wasting you time.

MaskRay commented 4 years ago

I know little about Windows... If you were using a POSIX OS, I would ask you to run ccls under CCLS_TRACEME=s and attach a debugger to the process.

receive RequestMessage: 0 is suspicious - it seems the id has been duplicated.

Have you tried (setq lsp-enable-links nil)?

Have you had success with a hello world project?

# On a *NIX, the instructions are:
mkdir /tmp/c
touch .ccls
git init  # project root indicator
echo 'int foo;' > a.cc
# open a.cc
JAGF009 commented 4 years ago

No luck with any of the two things.

The internet seems to agree that something like this might work, I'm too tired today to rebuild and try it, but I'll probably at least try it next week, this module seems to good to not try.

void traceMe() {
  // The maximum size of an environment variable is 65535
  DWORD size = 65535;
  std::wstring buff;
  buff.resize(size);
  size = GetEnvironmentVariableW(L"CCLS_TRACEME", buff.data(), size);
  buff.resize(size);
  if (buff == L"s") {
    waitForDebugger();
  }
}

void waitForDebugger() {
  while (!IsDebuggerPresent()) {
    Sleep(100);
  }
  DebugBreak();
}
JAGF009 commented 4 years ago

Ok, so I built a debug executable and attached to it.

I set up a couple of breakpoints, mainly on the stdin thread and the MessageHandler::run. I don't know much of the codebase, it could be great if you could tell me what I should look for.

I've also tried this with the Visual Code extension and got the same problem, so it seems to be unrelated to lsp-mode.

The problem happens after this response from the client: (this is from the client side)

[Trace - 09:40:23 ] Sending response 'client/registerCapability - (0)'. Processing request took 44ms
Params: {
  "jsonrpc": "2.0",
  "id": 0,
  "result": null
}

which is a response to this request

[Trace - 09:40:23 ] Received request 'client/registerCapability - (0).
Params: {
  "registrations": [
    {
      "registerOptions": {
        "watchers": [
          {
            "globPattern": "**/*"
          }
        ]
      },
      "method": "workspace/didChangeWatchedFiles",
      "id": "didChangeWatchedFiles"
    }
  ]
}

And this is the call stack when the exception occurs, seems to be freeing a null pointer. Probably something is happening on other thread that is the cause of this, hope something comes to mind.

MaskRay commented 4 years ago

https://paste.ofcode.org/FRkmGguGiLRugKDiGfQYFS

ccls.exe!ccls::`anonymous namespace'::buildPreamble(ccls::Session & session, ...

This looks like a clang problem in PrecompiledPreamble::Build. client/registerCapability is not related (it works on my machine).

Can you try

--- i/src/sema_manager.cc
+++ w/src/sema_manager.cc
@@ -304,7 +304,6 @@ buildCompilerInstance(Session &session, std::unique_ptr<CompilerInvocation> ci,                                  
       clang->getDiagnostics(), clang->getInvocation().TargetOpts));                                                                 
   if (!clang->hasTarget())
     return nullptr;
-  clang->getPreprocessorOpts().RetainRemappedFileBuffers = true;
   // Construct SourceManager with UserFilesAreVolatile: true because otherwise                                                      
   // RequiresNullTerminator: true may cause out-of-bounds read when a file is                                                       
   // mmap'ed but is saved concurrently.

(it will cause a memory leak but it should not cause a double-free) and see whether it works?

JAGF009 commented 4 years ago

It didn't fix it, and the error is the same :/

Tomorrow I'll try and do a bit more debbuging, see if I can come up with something.

Just as a question, could I attach lsp-mode to a process already running? I could build ccsl in WSL and then attach to that process, I could work around windows that way. I'd like this to work on windows, tho. It seems to be working for others.

Other question, when running ccls.exe --index=. --log-file=ccls.log -v 2 is the proccess supposed to stop after indexing the project? Because I had to manually stop it with C-c