Skip to content

Commit

Permalink
Major stability improvement for pipe server
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonarddeR committed Jul 27, 2023
1 parent b352325 commit e7b7f12
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 27 deletions.
8 changes: 4 additions & 4 deletions addon/globalPlugins/rdAccess/handlers/_remoteHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ def initIo(
self._dev = namedPipe.NamedPipeServer(
pipeName=pipeName,
onReceive=self._onReceive,
onReadError=self._onReadError,
onConnected=self._onConnected,
ioThread=ioThread
)
Expand All @@ -79,10 +78,11 @@ def __init__(
elif self._remoteSessionhasFocus is None:
self._remoteSessionhasFocus = False

def _onConnected(self):
def _onConnected(self, connected: bool = True):
if self._isSecureDesktopHandler:
self._remoteSessionhasFocus = True
self._handleDriverChanged(self._driver)
self._remoteSessionhasFocus = connected
if connected:
self._handleDriverChanged(self._driver)

def event_gainFocus(self, obj):
if self._isSecureDesktopHandler:
Expand Down
16 changes: 0 additions & 16 deletions addon/globalPlugins/rdAccess/secureDesktop.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,6 @@ class SecureDesktopHandler(AutoPropertyObject):
_ioThreadRef: weakref.ReferenceType[IoThread]
_brailleHandler: RemoteBrailleHandler
_speechHandler: RemoteSpeechHandler
_terminating: bool = False

def _handleRemoteDisconnect(self, handler: RemoteHandler, error: int) -> bool:
if self._terminating:
return True
winErr = WinError(error)
if isinstance(winErr, BrokenPipeError):
log.warning(f"Handling remote disconnect of secure desktop handler {handler}: {winErr}")
ioThread = self._ioThreadRef()
pipeName = handler._dev.pipeName
handler.terminate()
handler.__init__(ioThread=ioThread, pipeName=pipeName, isNamedPipeClient=False)
return True
return False

def __init__(self, ioThread: IoThread):
self._ioThreadRef = weakref.ref(ioThread)
Expand All @@ -53,7 +39,6 @@ def __init__(self, ioThread: IoThread):
self._speechHandler = self._initializeHandler(RemoteSpeechHandler)

def terminate(self):
self._terminating = True
self._speechHandler.terminate()
braille.handler.display.loadSettings()
self._brailleHandler.terminate()
Expand All @@ -63,5 +48,4 @@ def _initializeHandler(self, handlerType: typing.Type[HandlerTypeT]) -> HandlerT
sdId = f"NVDA_SD-{handlerType.driverType.name}"
sdPort = os.path.join(namedPipe.PIPE_DIRECTORY, sdId)
handler = handlerType(self._ioThreadRef(), sdPort, False)
handler.decide_remoteDisconnect.register(self._handleRemoteDisconnect)
return handler
40 changes: 33 additions & 7 deletions addon/lib/namedPipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,15 +135,14 @@ def _get_isAlive(self) -> bool:

class NamedPipeServer(NamedPipeBase):
_connected: bool = False
_onConnected: Optional[Callable[[], None]] = None
_onConnected: Optional[Callable[[bool], None]] = None

def __init__(
self,
pipeName: str,
onReceive: Callable[[bytes], None],
onReceiveSize: int = MAX_PIPE_MESSAGE_SIZE,
onConnected: Optional[Callable[[], None]] = None,
onReadError: Optional[Callable[[int], bool]] = None,
onConnected: Optional[Callable[[bool], None]] = None,
ioThread: Optional[IoThread] = None,
pipeMode: PipeMode = PipeMode.READMODE_BYTE,
pipeOpenMode: PipeOpenMode = (
Expand Down Expand Up @@ -172,7 +171,7 @@ def __init__(
pipeName,
fileHandle,
onReceive,
onReadError=onReadError,
onReadError=self._onReadError,
ioThread=ioThread,
pipeMode=pipeMode,
)
Expand Down Expand Up @@ -215,25 +214,52 @@ def _handleConnect(self):
raise WinError()
self.pipeProcessId = clientProcessId.value
self.pipeParentProcessId = getParentProcessId(self.pipeProcessId)
self._asyncRead()
super()._asyncRead()
if self._onConnected is not None:
self._onConnected()

def _onReadError(self, error: int):
winErr = WinError(error)
if isinstance(winErr, BrokenPipeError):
self.disconnect()
self._initialRead()
return True
return False

def _asyncRead(self, param: Optional[int] = None):
if not self._connected:
# _handleConnect will call _asyncRead when it is finished.
self._handleConnect()
else:
super()._asyncRead()

def disconnect(self):
if not windll.kernel32.DisconnectNamedPipe(self._file):
raise WinError()
self._connected = False
self.pipeProcessId = None
self.pipeParentProcessId = None
if self._onConnected:
self._onConnected(False)

def close(self):
self._onConnected = None
super().close()
if hasattr(self, "_file") and self._file is not INVALID_HANDLE_VALUE:
windll.kernel32.DisconnectNamedPipe(self._file)
self.disconnect()
self._onConnected = None
winKernel.closeHandle(self._file)
self._file = INVALID_HANDLE_VALUE

@property
def _ioDone(self):
return super()._ioDone

@_ioDone.setter
def _ioDone(self, value):
"""Hack, we don't want _ioDone to set itself to None.
"""
pass


class NamedPipeClient(NamedPipeBase):

Expand Down

0 comments on commit e7b7f12

Please sign in to comment.