nimsuggest: Added optional command line option '--clientProcessId:XXX' (#22969)

When it is specified, the nimsuggest instance monitors whether this
process is still alive. In case it's found to be dead, nimsuggest shuts
itself down. Currently only implemented on POSIX and Windows platforms.
The switch is silently ignored on other platforms. Note that the Nim
language server should still try to shut down its child nimsuggest
processes. This switch just adds extra protection against crashing Nim
language server and gets rid of the remaining nimsuggest processes,
which consume memory and system resources.
This commit is contained in:
Nikolay Nikolov
2023-11-24 20:55:53 +02:00
committed by GitHub
parent 816ddd8be7
commit 502a4486ae
3 changed files with 42 additions and 0 deletions

View File

@@ -442,6 +442,7 @@ type
expandPosition*: TLineInfo
currentConfigDir*: string # used for passPP only; absolute dir
clientProcessId*: int
proc parseNimVersion*(a: string): NimVer =

View File

@@ -12,6 +12,7 @@ import strformat
import algorithm
import tables
import times
import procmonitor
template tryImport(module) = import module
@@ -56,6 +57,7 @@ Options:
--address:HOST binds to that address, by default ""
--stdin read commands from stdin and write results to
stdout instead of using sockets
--clientProcessId:PID shutdown nimsuggest in case this process dies
--epc use emacs epc mode
--debug enable debug output
--log enable verbose logging to nimsuggest.log file
@@ -625,6 +627,9 @@ proc mainCommand(graph: ModuleGraph) =
open(requests)
open(results)
if graph.config.clientProcessId != 0:
hookProcMonitor(graph.config.clientProcessId)
case gMode
of mstdin: createThread(inputThread, replStdin, (gPort, gAddress))
of mtcp: createThread(inputThread, replTcp, (gPort, gAddress))
@@ -700,6 +705,8 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string; conf: ConfigRef) =
conf.suggestMaxResults = parseInt(p.val)
of "find":
findProject = true
of "clientprocessid":
conf.clientProcessId = parseInt(p.val)
else: processSwitch(pass, p, conf)
of cmdArgument:
let a = unixToNativePath(p.key)

View File

@@ -0,0 +1,34 @@
# Monitor a client process and shutdown the current process, if the client
# process is found to be dead
import os
when defined(posix):
import posix_utils
import posix
when defined(windows):
import winlean
when defined(posix):
proc monitorClientProcessIdThreadProc(pid: int) {.thread.} =
while true:
sleep(1000)
try:
sendSignal(Pid(pid), 0)
except:
discard kill(Pid(getCurrentProcessId()), cint(SIGTERM))
when defined(windows):
proc monitorClientProcessIdThreadProc(pid: int) {.thread.} =
var process = openProcess(SYNCHRONIZE, 0, DWORD(pid))
if process != 0:
discard waitForSingleObject(process, INFINITE)
discard closeHandle(process)
quit(0)
var tid: Thread[int]
proc hookProcMonitor*(pid: int) =
when defined(posix) or defined(windows):
createThread(tid, monitorClientProcessIdThreadProc, pid)