mirror of
https://github.com/golang/go
synced 2024-10-01 07:28:35 -06:00
d1d1f200c6
When the gopls daemon is automatically managed (-remote=auto), it will be started by one of the forwarder gopls processes that was in turn started by the editor. By default, this puts it in the same process group as the forwarder gopls. Some editors (at least Vim) send SIGTERM to the process groups of sidecar processes when exiting. This can cause the gopls daemon to terminate, thereby losing state. Rather than ignore SIGTERM (which is bound to be editor dependent anyway), let's just put the gopls daemon in a separate session. Updates golang/go#34111 Change-Id: I71386fb54b8c2efe1c565f59763f46693a7d48b0 Reviewed-on: https://go-review.googlesource.com/c/tools/+/221220 Run-TryBot: Robert Findley <rfindley@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
67 lines
1.9 KiB
Go
67 lines
1.9 KiB
Go
// Copyright 2020 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// +build darwin dragonfly freebsd linux netbsd solaris openbsd
|
|
|
|
package lsprpc
|
|
|
|
import (
|
|
"crypto/sha1"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"syscall"
|
|
)
|
|
|
|
func init() {
|
|
startRemote = startRemotePosix
|
|
autoNetworkAddress = autoNetworkAddressPosix
|
|
}
|
|
|
|
func startRemotePosix(goplsPath string, args ...string) error {
|
|
cmd := exec.Command(goplsPath, args...)
|
|
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
Setsid: true,
|
|
}
|
|
if err := cmd.Start(); err != nil {
|
|
return fmt.Errorf("starting remote gopls: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// autoNetworkAddress resolves an id on the 'auto' pseduo-network to a
|
|
// real network and address. On unix, this uses unix domain sockets.
|
|
func autoNetworkAddressPosix(goplsPath, id string) (network string, address string) {
|
|
// Especially when doing local development or testing, it's important that
|
|
// the remote gopls instance we connect to is running the same binary as our
|
|
// forwarder. So we encode a short hash of the binary path into the daemon
|
|
// socket name. If possible, we also include the buildid in this hash, to
|
|
// account for long-running processes where the binary has been subsequently
|
|
// rebuilt.
|
|
h := sha1.New()
|
|
cmd := exec.Command("go", "tool", "buildid", goplsPath)
|
|
cmd.Stdout = h
|
|
var pathHash []byte
|
|
if err := cmd.Run(); err == nil {
|
|
pathHash = h.Sum(nil)
|
|
} else {
|
|
log.Printf("error getting current buildid: %v", err)
|
|
sum := sha1.Sum([]byte(goplsPath))
|
|
pathHash = sum[:]
|
|
}
|
|
shortHash := fmt.Sprintf("%x", pathHash)[:6]
|
|
user := os.Getenv("USER")
|
|
if user == "" {
|
|
user = "shared"
|
|
}
|
|
basename := filepath.Base(goplsPath)
|
|
idComponent := ""
|
|
if id != "" {
|
|
idComponent = "-" + id
|
|
}
|
|
return "unix", filepath.Join(os.TempDir(), fmt.Sprintf("%s-%s-daemon.%s%s", basename, shortHash, user, idComponent))
|
|
}
|