nsf / gocode

An autocompletion daemon for the Go programming language
MIT License
5.01k stars 658 forks source link

gocode works only with 'gocode -s -debug' #270

Closed cpmech closed 9 years ago

cpmech commented 9 years ago

i've tried many things; but it works only with -s and/or -debug options i've updated everything to the latest version (including go source)

nsf commented 9 years ago

What do you mean it works only with -s? Does it mean it works only if you run it manually?

cpmech commented 9 years ago

Yes, it has to be run manually. Thanks for this great tool.

nsf commented 9 years ago

What's your OS?

cpmech commented 9 years ago

Debian unstable On 26 Jan 2015 22:06, "nsf" notifications@github.com wrote:

What's your OS?

— Reply to this email directly or view it on GitHub https://github.com/nsf/gocode/issues/270#issuecomment-71451366.

nsf commented 9 years ago

Hm, that's interesting. I expect (for some reason) potential problems on MacOSX, but on linux it should work really smoothly. You still haven't said (and I haven't asked) what's your editor? But it's really weird you see. Gocode binary is executed by the editor and then it tries to connect to a gocode server, if it fails to do so it starts one. The only reason why it will fail to execute itself is that gocode binary is not in the PATH somehow, but that's where confusion begins. Since editor executes gocode client, it should know about its location.

Try running which -a gocode in shell and tell me what it says.

cpmech commented 9 years ago

I'm using vim and gocode is available in PATH. which -a gocode produces: /home/myuname/mygo/bin/gocode gocode status works from any directory

Ok. I've installed Debian testing from scratch in a VirtualBox and Gocode works fine by following these (standard) steps: https://docs.google.com/document/d/1GCIWfievNzkCcDB-3bCixtf60hO61UbR_hJgBiGsJhE/edit?usp=sharing

I'm still puzzled why in my machine it does not work; it might be something in my .vimrc messing up; will try with a clean one.

cheers d

cpmech commented 9 years ago

with a clean .vimrc and .vim, in my machine, it still works only with 'gocode -s'. any ideas?

nsf commented 9 years ago

I can only help you by describing how exactly gocode works.

That's the two most important functions in the client: https://github.com/nsf/gocode/blob/master/client.go#L15-L71

Client tries to connect to gocode via unix socket, which is being found by using this function: https://github.com/nsf/gocode/blob/master/gocode.go#L23-L29

Here gocode assumes that os.TempDir() always returns the same path.

If the socket was not found or connecting to it fails, gocode assumes the server isn't running. It removes the socket and tries to run the server.. In order to do so it lookups the binary of itself via this function:

https://github.com/nsf/gocode/blob/master/os_posix.go#L16-L38

And after doing so, it tries to connect again. Apparently something along those lines fails. And I have no idea what. Try looking into your /tmp dir and see if running autocompletion in a text editor (without gocode server running) creates a socket there. Also see if you can find where gocode -s creates its socket. I assume things don't connect properly, but it may also be vim's fault.

cpmech commented 9 years ago

both 'gocode close' + vim and 'gocode -s' + vim create gocode-daemon.myuname in /tmp

with 'gocode -s', I can see that it rebuilds a package (code.google.com/p/gosl/utl) I'm using all the time, could this be the reason?

cpmech commented 9 years ago

it has to do with 'rebuilding package' utl... for instance:

2015/01/27 12:28:30 ------------------- 2015/01/27 12:28:30 rebuilding package 2015/01/27 12:28:30 package import: code.google.com/p/gosl/utl 2015/01/27 12:28:30 package object: /home/dorival/10.go/pkg/linux_amd64/code.google.com/p/gosl/utl.a 2015/01/27 12:28:30 package source dir: /home/dorival/10.go/src/code.google.com/p/gosl/utl 2015/01/27 12:28:30 package source files: [] 2015/01/27 12:28:30 build out: 2015/01/27 12:28:31 ------------------- 2015/01/27 12:28:31 rebuilding package 2015/01/27 12:28:31 package import: code.google.com/p/gosl/utl 2015/01/27 12:28:31 package object: /home/dorival/10.go/pkg/linux_amd64/code.google.com/p/gosl/utl.a 2015/01/27 12:28:31 package source dir: /home/dorival/10.go/src/code.google.com/p/gosl/utl 2015/01/27 12:28:31 package source files: [] 2015/01/27 12:28:32 build out:

what happens even when I'm not autocompleting utl

could be a problem with my package?

nsf commented 9 years ago

It could be, if you use gocode set autobuild true. Which is frankly an experimental feature and I'm not the author. But perhaps something is wrong along those lines? Is it your GOPATH? /home/dorival/10.go. Also keep in mind if you test gocode in a directory with a lot of files it can be a reason. Gocode searches all *.go files in the same dir and assumes they are from the package you're working on (if package clause matches). The fact that it rebuilds the package all the time is also weird. It should rebuild one only if the archive file was create before one of the package files:

https://github.com/nsf/gocode/blob/master/declcache.go#L191-L215

cpmech commented 9 years ago

interesting: the rebuilding package occurs only if we do go test in the utl package.

if we just go install from the utl directory, gocode stops rebuilding all the time.

i.e., by rm gosl/utl.a from the _linuxamd64...gosl directory and by running go install from utl, then gocode works even without the "-s" flag...

nsf commented 9 years ago

What I've noticed is that autobuild() function in gocode returns an error and nobody checks that error ever. Hold on I'll add the code which does so, maybe there is some kind of an error happening and it is being silently ignored.

nsf commented 9 years ago

Committed, but that's unlikely though. Weird stuff.

cpmech commented 9 years ago

I've checked it out; 'rebuilding' persists.

But I think I've found the problem: by calling go test, new files were being created under utl; these files were triggering gocode's rebuild routine. Nonetheless, those new files were merely test output (text) files. Thus, gocode will keep trying go install because it saw new files; but go install will not update the utl.a binary because it ignores these text files.

I've updated my utl testing routines to write to /tmp/ instead; thus (apparently) solving the issue.

Many thanks for your help.

dmitshur commented 9 years ago

Very interesting situation (and something to keep in mind when using autobuild), thanks for getting to the bottom of it and sharing your experience.

nsf commented 9 years ago

The question is. Even if rebuild is triggered, why gocode doesn't work in that situation? I mean the library file is there, autocompletion should work just fine.

cpmech commented 9 years ago

sure. i was wondering the same; but cannot answer because i can only see any output with 'gocode -s'; which works for all cases...

nsf commented 9 years ago

Well, if you don't mind touching gocode's source code, you can insert a "log" package output redirection at the beginning of the do_server() function in server.go. Also force the debug flag to be true by default and see what gocode server says when executed by the client. I.e.

// func do_server() in server.go
f, _ := os.Create("/tmp/gocode.log")
log.SetOutput(f)

// replace the default value of the flag with `true` in gocode.go
g_debug = flag.Bool("debug", false, "enable server-side debug mode")

Or perhaps I could add another settings option, such as force-debug which is a string and points to the filename which would be used as a logging output. Also if it's not empty, the debug flag will be always forced.

Hold on.. will do so.

nsf commented 9 years ago

Done. Run: gocode set force-debug-output /tmp/gocode.log. And see what it prints when you run the client.

cpmech commented 9 years ago

By using the force-debug-output option; it does work even after creating an empty file in the third-party package utl although this package gets rebuild constantly. I've got a problem at the beginning after 'touch anyfile.txt' in utl; but cannot get it any longer. I'll post later on if something happens...

cpmech commented 9 years ago

I don't know what's going on... With the force-debug-output option, autocomplete works. I've looked into server.go in order to do some print outs but will not be able to help here...

I'm wondering if I'm the only one with this problem. It should be simple to be reproduced by others. Just grab a third-party package and use it in your hello.go. Then, with autobuild on + no force-debug-output, create a new file (say test.txt) in this third-party package' directory to see that autocompletion stops in vim...

nsf commented 9 years ago

Will try it out, but tomorrow.

nsf commented 9 years ago

Tried it out. I see exactly what you're saying.

Running gocode manually, -s or -s -debug - works.

Running gocode implicitly with force-debug-output true - works.

Running gocode implicitly with default settings - doesn't show anything.

Will try to figure out (somehow) what's wrong.

nsf commented 9 years ago

Well, that's how it dies for some reason, the server is actually running, but it fails to communicate somehow:

[nsf @ gobug]$ gocode -in gobug.go autocomplete gobug.go 78
panic: gob: bad data: undefined type CommonType = struct { Name string; Id int; }

goroutine 1 [running]:
main.client_auto_complete(0xc20800a540, 0xc20804b900, 0x51, 0x251, 0xc20801f960, 0x1c, 0x4e, 0x8879d0, 0x5, 0x890390, ...)
        /home/nsf/waytogo/src/github.com/nsf/gocode/rpc.go:38 +0x1c9
main.cmd_auto_complete(0xc20800a540)
        /home/nsf/waytogo/src/github.com/nsf/gocode/client.go:146 +0x169
main.do_client(0x0)
        /home/nsf/waytogo/src/github.com/nsf/gocode/client.go:44 +0x594
main.main()
        /home/nsf/waytogo/src/github.com/nsf/gocode/gocode.go:69 +0x77

goroutine 7 [chan receive]:
main.func·020()
        /home/nsf/waytogo/src/github.com/nsf/gocode/utils.go:113 +0x7d
created by main.new_file_reader
        /home/nsf/waytogo/src/github.com/nsf/gocode/utils.go:117 +0xe7
nsf commented 9 years ago

Okay, I've found the reason why it happens. I start the server process via os.StartProcess and I use "nil" for standard file descriptors (stdin/stdout/stderr). Because "autobuild" feature was writing unconditionally to "log", it was causing problems. A better solution would be to open os.DevNull and pass it to os.StartProcess.

I'll fix the problem. Soon.

For now there is a temporary fix, which prevents autobuild from writing to log without -debug flag.

dmitshur commented 9 years ago

I start the server process via os.StartProcess and I use "nil" for standard file descriptors (stdin/stdout/stderr).

That's something that the higher-level os/exec package does for you, if you leave Stdin/Stdout/Stderr as nil, right?

http://godoc.org/os/exec#Cmd.Stdin

// If Stdin is nil, the process reads from the null device (os.DevNull).

// If either is nil, Run connects the corresponding file descriptor
// to the null device (os.DevNull).

Yes, it does. Just wanted to verify.

nsf commented 9 years ago

Sadly it doesn't allow me to "Release" the process.

dmitshur commented 9 years ago

Can you use Cmd.Process? If not, why not?

nsf commented 9 years ago

Maybe I can, but it's scary. While the package can do everything I want, its API is not modeled for doing so. I don't mind calling os.StartProcess myself.

dmitshur commented 9 years ago

Makes sense, thanks.

cpmech commented 9 years ago

thanks