Skip to content

Commit

Permalink
Merge pull request #154 from arduino/fix-temp-file-cleanup
Browse files Browse the repository at this point in the history
Fix temp file cleanup and reorganized temp dir structure
  • Loading branch information
cmaglie authored Aug 17, 2023
2 parents 6c64232 + ca7d9ae commit 4752595
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 17 deletions.
59 changes: 45 additions & 14 deletions ls/ls.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"io"
"log"
"os"
"os/exec"
"strconv"
"strings"
"sync"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down
7 changes: 6 additions & 1 deletion ls/lsp_client_clangd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
2 changes: 0 additions & 2 deletions ls/lsp_server_ide.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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")
Expand Down

0 comments on commit 4752595

Please sign in to comment.