Skip to content

Commit 4752595

Browse files
authored
Merge pull request #154 from arduino/fix-temp-file-cleanup
Fix temp file cleanup and reorganized temp dir structure
2 parents 6c64232 + ca7d9ae commit 4752595

File tree

4 files changed

+65
-17
lines changed

4 files changed

+65
-17
lines changed

ls/ls.go

+45-14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"io"
2323
"log"
2424
"os"
25+
"os/exec"
2526
"strconv"
2627
"strings"
2728
"sync"
@@ -50,8 +51,10 @@ type INOLanguageServer struct {
5051

5152
progressHandler *progressProxyHandler
5253
closing chan bool
54+
removeTempMutex sync.Mutex
5355
clangdStarted *sync.Cond
5456
dataMux sync.RWMutex
57+
tempDir *paths.Path
5558
buildPath *paths.Path
5659
buildSketchRoot *paths.Path
5760
buildSketchCpp *paths.Path
@@ -144,18 +147,21 @@ func NewINOLanguageServer(stdin io.Reader, stdout io.Writer, config *Config) *IN
144147
if tmp, err := paths.MkTempDir("", "arduino-language-server"); err != nil {
145148
log.Fatalf("Could not create temp folder: %s", err)
146149
} else {
147-
ls.buildPath = tmp.Canonical()
148-
ls.buildSketchRoot = ls.buildPath.Join("sketch")
150+
ls.tempDir = tmp.Canonical()
149151
}
150-
151-
if tmp, err := paths.MkTempDir("", "arduino-language-server"); err != nil {
152+
ls.buildPath = ls.tempDir.Join("build")
153+
ls.buildSketchRoot = ls.buildPath.Join("sketch")
154+
if err := ls.buildPath.MkdirAll(); err != nil {
155+
log.Fatalf("Could not create temp folder: %s", err)
156+
}
157+
ls.fullBuildPath = ls.tempDir.Join("fullbuild")
158+
if err := ls.fullBuildPath.MkdirAll(); err != nil {
152159
log.Fatalf("Could not create temp folder: %s", err)
153-
} else {
154-
ls.fullBuildPath = tmp.Canonical()
155160
}
156161

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

1381+
func (ls *INOLanguageServer) removeTemporaryFiles(logger jsonrpc.FunctionLogger) {
1382+
ls.removeTempMutex.Lock()
1383+
defer ls.removeTempMutex.Unlock()
1384+
1385+
if ls.tempDir == nil {
1386+
// Nothing to remove
1387+
return
1388+
}
1389+
1390+
// Start a detached process to remove the temp files
1391+
cwd, err := os.Getwd()
1392+
if err != nil {
1393+
logger.Logf("Error getting current working directory: %s", err)
1394+
return
1395+
}
1396+
cmd := exec.Command(os.Args[0], "remove-temp-files", ls.tempDir.String())
1397+
cmd.Dir = cwd
1398+
if err := cmd.Start(); err != nil {
1399+
logger.Logf("Error starting remove-temp-files process: %s", err)
1400+
return
1401+
}
1402+
1403+
// The process is now started, we can reset the paths
1404+
ls.buildPath, ls.fullBuildPath, ls.buildSketchRoot, ls.tempDir = nil, nil, nil, nil
1405+
1406+
// Detach the process so it can continue running even if the parent process exits
1407+
if err := cmd.Process.Release(); err != nil {
1408+
logger.Logf("Error detaching remove-temp-files process: %s", err)
1409+
return
1410+
}
1411+
}
1412+
13741413
// Close closes all the json-rpc connections and clean-up temp folders.
13751414
func (ls *INOLanguageServer) Close() {
13761415
if ls.Clangd != nil {
@@ -1381,14 +1420,6 @@ func (ls *INOLanguageServer) Close() {
13811420
close(ls.closing)
13821421
ls.closing = nil
13831422
}
1384-
if ls.buildPath != nil {
1385-
ls.buildPath.RemoveAll()
1386-
ls.buildPath = nil
1387-
}
1388-
if ls.fullBuildPath != nil {
1389-
ls.fullBuildPath.RemoveAll()
1390-
ls.fullBuildPath = nil
1391-
}
13921423
}
13931424

13941425
// CloseNotify returns a channel that is closed when the InoHandler is closed

ls/lsp_client_clangd.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,12 @@ func newClangdLSPClient(logger jsonrpc.FunctionLogger, dataFolder *paths.Path, l
6060
logger.Logf(" Starting clangd: %s", strings.Join(args, " "))
6161
var clangdStdin io.WriteCloser
6262
var clangdStdout, clangdStderr io.ReadCloser
63-
if clangdCmd, err := executils.NewProcess(nil, args...); err != nil {
63+
var extraEnv []string
64+
if ls.tempDir != nil {
65+
extraEnv = append(extraEnv, "TMPDIR="+ls.tempDir.String()) // For unix-based systems
66+
extraEnv = append(extraEnv, "TMP="+ls.tempDir.String()) // For Windows
67+
}
68+
if clangdCmd, err := executils.NewProcess(extraEnv, args...); err != nil {
6469
panic("starting clangd: " + err.Error())
6570
} else if cin, err := clangdCmd.StdinPipe(); err != nil {
6671
panic("getting clangd stdin: " + err.Error())

ls/lsp_server_ide.go

-2
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,6 @@ func (server *IDELSPServer) WorkspaceDidChangeConfiguration(logger jsonrpc.Funct
303303
//
304304
// Since ALS doesn’t have any workspace configuration yet,
305305
// ignore it.
306-
return
307-
308306
}
309307

310308
// WorkspaceDidChangeWatchedFiles is not implemented

main.go

+14
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"os/signal"
1313
"os/user"
1414
"path"
15+
"strings"
1516

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

2223
func main() {
24+
if len(os.Args) > 1 && os.Args[1] == "remove-temp-files" {
25+
for _, tmpFile := range os.Args[2:] {
26+
// SAFETY CHECK
27+
if !strings.Contains(tmpFile, "arduino-language-server") {
28+
fmt.Println("Could not remove extraneous temp folder:", tmpFile)
29+
os.Exit(1)
30+
}
31+
32+
paths.New(tmpFile).RemoveAll()
33+
}
34+
return
35+
}
36+
2337
clangdPath := flag.String(
2438
"clangd", "",
2539
"Path to clangd executable")

0 commit comments

Comments
 (0)