summary refs log tree commit diff stats
path: root/nimsuggest
diff options
context:
space:
mode:
authorNikolay Nikolov <nickysn@gmail.com>2023-11-24 20:55:53 +0200
committerGitHub <noreply@github.com>2023-11-24 19:55:53 +0100
commit502a4486aeb8d0a5dcdf86540522d3dc16960536 (patch)
treeb53b42cf0b5aee7ef155aa3dd0d7a9d666817161 /nimsuggest
parent816ddd8be7cbae2513469cfccc516169a0cad7b2 (diff)
downloadNim-502a4486aeb8d0a5dcdf86540522d3dc16960536.tar.gz
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.
Diffstat (limited to 'nimsuggest')
-rw-r--r--nimsuggest/nimsuggest.nim7
-rw-r--r--nimsuggest/procmonitor.nim34
2 files changed, 41 insertions, 0 deletions
diff --git a/nimsuggest/nimsuggest.nim b/nimsuggest/nimsuggest.nim
index ca0f5112e..03a6e32e1 100644
--- a/nimsuggest/nimsuggest.nim
+++ b/nimsuggest/nimsuggest.nim
@@ -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)
diff --git a/nimsuggest/procmonitor.nim b/nimsuggest/procmonitor.nim
new file mode 100644
index 000000000..0f1ba1e0d
--- /dev/null
+++ b/nimsuggest/procmonitor.nim
@@ -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)