Skip to content

Conversation

@s4c5
Copy link

@s4c5 s4c5 commented Mar 5, 2019

When using ccls from emacs LSP, I would constantly get "not indexed" errors.
The source code being indexed is on a GPFS filesystem that has a "friendly" pathname, and the actual (more convoluted) gpfs pathname.
ccls would index the file under the convoluted pathname, then try to retrieve it using the friendly pathname, resulting in constant "not indexed" errors. By forcing ccls to use the full pathname with this patch, it will always uses the same key to reference the source code index, and always gets the correct result.
ccls was completely borken for me and with this patch it is working flawlessly. I would guess that this multiple-pathname problem would also be an issue for anyone with symlinks in their projects, this patch should fix those cases as well.

@MaskRay
Copy link
Owner

MaskRay commented Mar 5, 2019

Adding realpath() logic to LowerPathIfInsensitive is not a good fix. This function isn't expected to accept non-absolute path arguments. Can you give me the stacktrace when LowerPathIfInsensitive receives a non-absolute path argument?

@MaskRay MaskRay force-pushed the master branch 3 times, most recently from a728086 to 5e15f51 Compare March 5, 2019 06:55
@s4c5
Copy link
Author

s4c5 commented Mar 5, 2019

#0  ccls::MessageHandler::FindOrFail (this=0x7fffffff12a0, path=..., reply=..., out_file_id=0x0) at /home/s4c5/emacs_support/ccls/src/message_handler.cc:279
#1  0x000000000058d3a2 in ccls::MessageHandler::textDocument_codeAction (this=0x7fffffff12a0, param=..., reply=...)
    at /home/s4c5/emacs_support/ccls/src/messages/textDocument_code.cc:38
#2  0x0000000000479b95 in void ccls::MessageHandler::Bind<ccls::CodeActionParam>(char const*, void (ccls::MessageHandler::*)(ccls::CodeActionParam&, ccls::ReplyOnce&))::{lambda(ccls::JsonReader&, ccls::ReplyOnce&)#1}::operator()(ccls::JsonReader&, ccls::ReplyOnce&) const (this=0x7fffffff12a0, reader=..., reply=...)                                         
    at /home/s4c5/emacs_support/ccls/src/message_handler.cc:165
#3  0x0000000000484fb3 in std::_Function_handler<void (ccls::JsonReader&, ccls::ReplyOnce&), void ccls::MessageHandler::Bind<ccls::CodeActionParam>(char const*, void (ccls::MessageHandler::*)(ccls::CodeActionParam&, ccls::ReplyOnce&))::{lambda(ccls::JsonReader&, ccls::ReplyOnce&)#1}>::_M_invoke(std::_Any_data const&, ccls::JsonReader&, ccls::ReplyOnce&) (
    __functor=..., __args#0=..., __args#1=...) at /physical/gpfs/rloc-grpusers/rloc_grp_users01/modules/linux/mods_linux/gcc-8.1.0/include/c++/8.1.0/bits/std_function.h:297
#4  0x000000000047b47b in std::function<void (ccls::JsonReader&, ccls::ReplyOnce&)>::operator()(ccls::JsonReader&, ccls::ReplyOnce&) const (this=0x1d35c38, __args#0=...,
    __args#1=...) at /physical/gpfs/rloc-grpusers/rloc_grp_users01/modules/linux/mods_linux/gcc-8.1.0/include/c++/8.1.0/bits/std_function.h:687
#5  0x000000000046edc3 in ccls::MessageHandler::Run (this=0x7fffffff12a0, msg=...) at /home/s4c5/emacs_support/ccls/src/message_handler.cc:223
#6  0x0000000000498ad8 in ccls::pipeline::MainLoop () at /home/s4c5/emacs_support/ccls/src/pipeline.cc:630
#7  0x000000000041dfa5 in main (argc=2, argv=0x7fffffff2088) at /home/s4c5/emacs_support/ccls/src/main.cc:158
(gdb) 

This is a stacktrace to a FindOrFail when it is looking for the "friendly" non-absolute pathname. The lookup fails because the "full" filename was used to index the file.
You can see the two different filenames referenced in the log:

14:45:57 indexer1         pipeline.cc:375 I store index for /physical/gpfs/rloc-grpusers/rloc_grp_users01/home_files/grp/s4c5/dev/baseproj/mainproj/mainproj/srcfile.cpp (delta: 0)                                                                                                                                                                            
14:46:00 ccls         message_handler.cc:279 I *NARF* file not found /home/s4c5/dev/baseproj/mainproj/mainproj/srcfile.cpp

I can do additional logging or more breakpoints as needed

note:

$ ls -ld /home/s4c5
/home/s4c5 -> /physical/gpfs/rloc-grpusers/rloc_grp_users01/home_files/grp/s4c5

/home/s4c5 is a symlink to a more convoluted gpfs pathname

@madscientist
Copy link
Contributor

Hm... this might be the same problem I'm seeing with issue #242 (still happening as of this past weekend although I totally understand why you closed it given that I've not had anything useful to say). I just realized that my Git repository path contains a symlink to a different location. Maybe I'll try without that and see if I still get the same behavior.

// use this opportunity to get full path
char *rpbuf = NULL;
std::string fullpath;
rpbuf = realpath(path.c_str(), NULL);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say that since project is based on c++17 it worth to use std::filesystem

https://en.cppreference.com/w/cpp/filesystem/absolute

@MaskRay
Copy link
Owner

MaskRay commented Mar 6, 2019

  • The project root directory may be a symlink. The decision whether the symlink should be followed is on the client side.
    I believe many editors follow symlinks => there is no confusing part.
    If the editor doesn't (/tmp/symlink/ resolves to /tmp/real/ but the former is sent by the language client as the root directory), ccls should not convert /tmp/real/a.cc to /tmp/symlink/a.cc. In this case, the user shouldn't open /tmp/real/b.cc directly (I'll call it "unsolicited open"), as the editor doesn't know if there is other non-canonical path (/tmp/symlink/b.cc) and it'll cause trouble when /tmp/symlink/b.cc is later provided as a cross reference target.
    In addition, if the editor sometimes follows the symlink and sometimes not, e.g. the language client sometimes uses file:///tmp/symlink/a.cc and sometimes file:///real/a.cc => there is nothing sensible for ccls to do.
  • Some files/directories under the root directory are symlinks. If a file has one symlink, the file can be referenced by either the canonical name or the symlink name. There is no distinction in clang. The clang internals always follow symlinks and the original filenames may be lost. For this case, there's really nothing sensible for ccls to do.

@s4c5
Copy link
Author

s4c5 commented Mar 6, 2019

Hm... this might be the same problem I'm seeing with issue #242

You can see evidence of the problem if you look in the .ccls-cache directory in your project.
When I was seeing the pathname-aliasing problem, I had multiple "equivalent" paths showing up in the .ccls-cache. One would have the indexed data, the other would be empty.

@s4c5
Copy link
Author

s4c5 commented Mar 6, 2019

I can add some code to always use the project root directory as passed from the language client as-is. Will that fix your issue?

It'd be worth a try. I haven't tracked down where the two different path versions are coming from. I suppose its possible that the client itself references the file by different pathnames at various times when communicating with ccls, in which case ccls would still need to normalize the two paths.

@MaskRay
Copy link
Owner

MaskRay commented Mar 7, 2019

See my updated comment in #304 (comment)

You can see evidence of the problem if you look in the .ccls-cache directory in your project.

It'd be better if you clearly state which is the real path and which is the symlink.

@MaskRay
Copy link
Owner

MaskRay commented Mar 10, 2019

Superseded by #314

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants