Skip to content

Commit 753c89c

Browse files
committed
fix: extension not terminating sometimes on vscode exit
Fixes: #139
1 parent 3f626cc commit 753c89c

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
3+
__all__ = ["pid_exists"]
4+
5+
if os.name == "posix":
6+
7+
def pid_exists(pid: int) -> bool:
8+
import errno
9+
10+
if pid < 0:
11+
return False
12+
try:
13+
os.kill(pid, 0)
14+
except OSError as e:
15+
return e.errno == errno.EPERM
16+
else:
17+
return True
18+
19+
else:
20+
21+
def pid_exists(pid: int) -> bool:
22+
import ctypes
23+
24+
kernel32 = ctypes.windll.kernel32
25+
synchronize: int = 0x100000
26+
27+
process = kernel32.OpenProcess(synchronize, 0, pid)
28+
if process != 0:
29+
kernel32.CloseHandle(process)
30+
return True
31+
return False

packages/language_server/src/robotcode/language_server/common/protocol.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
UnregistrationParams,
2929
WorkspaceFolder,
3030
)
31+
from robotcode.core.utils.process import pid_exists
3132
from robotcode.jsonrpc2.protocol import (
3233
JsonRPCErrorException,
3334
JsonRPCErrors,
@@ -114,7 +115,7 @@ class LanguageServerProtocol(JsonRPCProtocol):
114115
def __init__(self, server: JsonRPCServer[Any]):
115116
super().__init__()
116117
self.server = server
117-
118+
self.parent_process_id: Optional[int] = None
118119
self.initialization_options: Any = None
119120
self.client_info: Optional[InitializeParamsClientInfoType] = None
120121
self._workspace: Optional[Workspace] = None
@@ -174,6 +175,20 @@ def _collect_capabilities(self) -> ServerCapabilities:
174175

175176
return base_capabilities
176177

178+
PARENT_PROCESS_WATCHER_INTERVAL = 5
179+
180+
def start_parent_process_watcher(self) -> None:
181+
if self.parent_process_id and self.loop:
182+
self.loop.call_later(self.PARENT_PROCESS_WATCHER_INTERVAL, self._parent_process_watcher)
183+
184+
def _parent_process_watcher(self) -> None:
185+
if not self.parent_process_id:
186+
return
187+
if not pid_exists(self.parent_process_id):
188+
self.__logger.error(lambda: f"Parent process {self.parent_process_id} is dead, exiting...")
189+
exit(2)
190+
self.start_parent_process_watcher()
191+
177192
@rpc_method(name="initialize", param_type=InitializeParams)
178193
@__logger.call
179194
async def _initialize(
@@ -186,9 +201,14 @@ async def _initialize(
186201
client_info: Optional[InitializeParamsClientInfoType] = None,
187202
workspace_folders: Optional[List[WorkspaceFolder]] = None,
188203
work_done_token: Optional[ProgressToken] = None,
204+
process_id: Optional[int] = None,
189205
*args: Any,
190206
**kwargs: Any,
191207
) -> InitializeResult:
208+
self.parent_process_id = process_id
209+
if self.parent_process_id and pid_exists(self.parent_process_id):
210+
self.start_parent_process_watcher()
211+
192212
self.trace = trace or TraceValues.OFF
193213
self.client_info = client_info
194214

src/robotcode/cli/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ def robotcode(
190190
if debugpy_wait_for_client:
191191
app.verbose("Waiting for debugpy client to connect...")
192192
wait_for_debugpy_connected()
193+
194+
app.verbose("Debugpy session started")
193195
else:
194196
app.verbose("Could not start debugpy session. Enable logging for more information.")
195197

0 commit comments

Comments
 (0)