Skip to content

Fix temp file cleanup and reorganized temp dir structure #154

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Aug 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 45 additions & 14 deletions ls/ls.go
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@ import (
"io"
"log"
"os"
"os/exec"
"strconv"
"strings"
"sync"
@@ -50,8 +51,10 @@ type INOLanguageServer struct {

progressHandler *progressProxyHandler
closing chan bool
removeTempMutex sync.Mutex
clangdStarted *sync.Cond
dataMux sync.RWMutex
tempDir *paths.Path
buildPath *paths.Path
buildSketchRoot *paths.Path
buildSketchCpp *paths.Path
@@ -144,18 +147,21 @@ func NewINOLanguageServer(stdin io.Reader, stdout io.Writer, config *Config) *IN
if tmp, err := paths.MkTempDir("", "arduino-language-server"); err != nil {
log.Fatalf("Could not create temp folder: %s", err)
} else {
ls.buildPath = tmp.Canonical()
ls.buildSketchRoot = ls.buildPath.Join("sketch")
ls.tempDir = tmp.Canonical()
}

if tmp, err := paths.MkTempDir("", "arduino-language-server"); err != nil {
ls.buildPath = ls.tempDir.Join("build")
ls.buildSketchRoot = ls.buildPath.Join("sketch")
if err := ls.buildPath.MkdirAll(); err != nil {
log.Fatalf("Could not create temp folder: %s", err)
}
ls.fullBuildPath = ls.tempDir.Join("fullbuild")
if err := ls.fullBuildPath.MkdirAll(); err != nil {
log.Fatalf("Could not create temp folder: %s", err)
} else {
ls.fullBuildPath = tmp.Canonical()
}

logger.Logf("Initial board configuration: %s", ls.config.Fqbn)
logger.Logf("%s", globals.VersionInfo.String())
logger.Logf("Language server temp directory: %s", ls.tempDir)
logger.Logf("Language server build path: %s", ls.buildPath)
logger.Logf("Language server build sketch root: %s", ls.buildSketchRoot)
logger.Logf("Language server FULL build path: %s", ls.fullBuildPath)
@@ -387,6 +393,7 @@ func (ls *INOLanguageServer) shutdownReqFromIDE(ctx context.Context, logger json
close(done)
}()
_, _ = ls.Clangd.conn.Shutdown(context.Background())
ls.removeTemporaryFiles(logger)
<-done
return nil
}
@@ -1371,6 +1378,38 @@ func (ls *INOLanguageServer) setTraceNotifFromIDE(logger jsonrpc.FunctionLogger,
ls.Clangd.conn.SetTrace(params)
}

func (ls *INOLanguageServer) removeTemporaryFiles(logger jsonrpc.FunctionLogger) {
ls.removeTempMutex.Lock()
defer ls.removeTempMutex.Unlock()

if ls.tempDir == nil {
// Nothing to remove
return
}

// Start a detached process to remove the temp files
cwd, err := os.Getwd()
if err != nil {
logger.Logf("Error getting current working directory: %s", err)
return
}
cmd := exec.Command(os.Args[0], "remove-temp-files", ls.tempDir.String())
cmd.Dir = cwd
if err := cmd.Start(); err != nil {
logger.Logf("Error starting remove-temp-files process: %s", err)
return
}

// The process is now started, we can reset the paths
ls.buildPath, ls.fullBuildPath, ls.buildSketchRoot, ls.tempDir = nil, nil, nil, nil

// Detach the process so it can continue running even if the parent process exits
if err := cmd.Process.Release(); err != nil {
logger.Logf("Error detaching remove-temp-files process: %s", err)
return
}
}

// Close closes all the json-rpc connections and clean-up temp folders.
func (ls *INOLanguageServer) Close() {
if ls.Clangd != nil {
@@ -1381,14 +1420,6 @@ func (ls *INOLanguageServer) Close() {
close(ls.closing)
ls.closing = nil
}
if ls.buildPath != nil {
ls.buildPath.RemoveAll()
ls.buildPath = nil
}
if ls.fullBuildPath != nil {
ls.fullBuildPath.RemoveAll()
ls.fullBuildPath = nil
}
}

// CloseNotify returns a channel that is closed when the InoHandler is closed
7 changes: 6 additions & 1 deletion ls/lsp_client_clangd.go
Original file line number Diff line number Diff line change
@@ -60,7 +60,12 @@ func newClangdLSPClient(logger jsonrpc.FunctionLogger, dataFolder *paths.Path, l
logger.Logf(" Starting clangd: %s", strings.Join(args, " "))
var clangdStdin io.WriteCloser
var clangdStdout, clangdStderr io.ReadCloser
if clangdCmd, err := executils.NewProcess(nil, args...); err != nil {
var extraEnv []string
if ls.tempDir != nil {
extraEnv = append(extraEnv, "TMPDIR="+ls.tempDir.String()) // For unix-based systems
extraEnv = append(extraEnv, "TMP="+ls.tempDir.String()) // For Windows
}
if clangdCmd, err := executils.NewProcess(extraEnv, args...); err != nil {
panic("starting clangd: " + err.Error())
} else if cin, err := clangdCmd.StdinPipe(); err != nil {
panic("getting clangd stdin: " + err.Error())
2 changes: 0 additions & 2 deletions ls/lsp_server_ide.go
Original file line number Diff line number Diff line change
@@ -303,8 +303,6 @@ func (server *IDELSPServer) WorkspaceDidChangeConfiguration(logger jsonrpc.Funct
//
// Since ALS doesn’t have any workspace configuration yet,
// ignore it.
return

}

// WorkspaceDidChangeWatchedFiles is not implemented
14 changes: 14 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@ import (
"os/signal"
"os/user"
"path"
"strings"

"github.com/arduino/arduino-language-server/ls"
"github.com/arduino/arduino-language-server/streams"
@@ -20,6 +21,19 @@ import (
)

func main() {
if len(os.Args) > 1 && os.Args[1] == "remove-temp-files" {
for _, tmpFile := range os.Args[2:] {
// SAFETY CHECK
if !strings.Contains(tmpFile, "arduino-language-server") {
fmt.Println("Could not remove extraneous temp folder:", tmpFile)
os.Exit(1)
}

paths.New(tmpFile).RemoveAll()
}
return
}

clangdPath := flag.String(
"clangd", "",
"Path to clangd executable")