Skip to content

Commit 6e16659

Browse files
committed
fix: correct handling error in server->client JSON RPC requests
1 parent 54e329e commit 6e16659

File tree

2 files changed

+80
-16
lines changed
  • packages

2 files changed

+80
-16
lines changed

packages/jsonrpc2/src/robotcode/jsonrpc2/protocol.py

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,65 @@ def set_result(f: asyncio.Future[Any], r: Any, ev: threading.Event) -> None:
624624

625625
@__logger.call
626626
async def handle_error(self, message: JsonRPCError) -> None:
627-
raise JsonRPCErrorException(message.error.code, message.error.message, message.error.data)
627+
if message.id is None:
628+
error = "Invalid response. Response id is null."
629+
self.__logger.warning(error)
630+
raise JsonRPCErrorException(message.error.code, message.error.message, message.error.data)
631+
632+
with self._sended_request_lock:
633+
entry = self._sended_request.pop(message.id, None)
634+
635+
if entry is None:
636+
error = f"Invalid response. Could not find id '{message.id}' in request list."
637+
self.__logger.warning(error)
638+
raise JsonRPCErrorException(message.error.code, message.error.message, message.error.data)
639+
640+
try:
641+
if not entry.future.done():
642+
res = None
643+
if message.result is not None:
644+
res = from_dict(message.result, entry.result_type)
645+
if entry.future.get_loop() == asyncio.get_running_loop():
646+
entry.future.set_exception(
647+
JsonRPCErrorException(message.error.code, message.error.message, message.error.data)
648+
)
649+
else:
650+
if entry.future.get_loop().is_running():
651+
652+
def set_result(f: asyncio.Future[Any], r: Any, ev: threading.Event) -> None:
653+
try:
654+
if not f.done() and f.get_loop().is_running():
655+
f.set_exception(
656+
JsonRPCErrorException(
657+
message.error.code, message.error.message, message.error.data
658+
)
659+
)
660+
finally:
661+
ev.set()
662+
663+
done = threading.Event()
664+
665+
entry.future.get_loop().call_soon_threadsafe(set_result, entry.future, res, done)
666+
667+
start = time.monotonic()
668+
while not done.is_set():
669+
if time.monotonic() - start > 120:
670+
raise TimeoutError("Can't set future result.")
671+
672+
await asyncio.sleep(0)
673+
674+
else:
675+
self.__logger.warning(lambda: f"Response {entry!r} loop is not running.")
676+
677+
except (SystemExit, KeyboardInterrupt):
678+
raise
679+
except BaseException as e:
680+
if not entry.future.done():
681+
if entry.future.get_loop() == asyncio.get_running_loop():
682+
entry.future.set_exception(e)
683+
else:
684+
if entry.future.get_loop().is_running():
685+
entry.future.get_loop().call_soon_threadsafe(entry.future.set_exception, e)
628686

629687
@staticmethod
630688
def _convert_params(

packages/language_server/src/robotcode/language_server/common/parts/workspace.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
)
6969
from robotcode.core.uri import Uri
7070
from robotcode.core.utils.path import path_is_relative_to
71-
from robotcode.jsonrpc2.protocol import rpc_method
71+
from robotcode.jsonrpc2.protocol import JsonRPCErrorException, rpc_method
7272
from robotcode.language_server.common.has_extend_capabilities import (
7373
HasExtendCapabilities,
7474
)
@@ -351,20 +351,26 @@ async def get_configuration_raw(
351351
and self.parent.client_capabilities.workspace.configuration
352352
and request
353353
):
354-
r = await self.parent.send_request_async(
355-
"workspace/configuration",
356-
ConfigurationParams(
357-
items=[
358-
ConfigurationItem(
359-
scope_uri=str(scope_uri) if isinstance(scope_uri, Uri) else scope_uri,
360-
section=section,
361-
)
362-
]
363-
),
364-
list,
365-
)
366-
367-
return r[0] if r is not None else None
354+
try:
355+
r = await self.parent.send_request_async(
356+
"workspace/configuration",
357+
ConfigurationParams(
358+
items=[
359+
ConfigurationItem(
360+
scope_uri=str(scope_uri) if isinstance(scope_uri, Uri) else scope_uri,
361+
section=section,
362+
)
363+
]
364+
),
365+
list,
366+
)
367+
368+
return r[0] if r is not None else None
369+
except asyncio.CancelledError:
370+
raise
371+
except JsonRPCErrorException as e:
372+
self._logger.warning(str(e))
373+
pass
368374

369375
result = self.settings
370376
for sub_key in str(section).split("."):

0 commit comments

Comments
 (0)