Skip to content

Robustness: Handle stale COM objects and RPC server unavailability#57

Open
amirf147 wants to merge 1 commit into
mirober:masterfrom
amirf147:fix/rpc-server-unavailable
Open

Robustness: Handle stale COM objects and RPC server unavailability#57
amirf147 wants to merge 1 commit into
mirober:masterfrom
amirf147:fix/rpc-server-unavailable

Conversation

@amirf147

Copy link
Copy Markdown

This PR addresses issues where pyvda becomes unresponsive after a Windows Explorer restart or other events that cause the Virtual Desktop COM objects to become stale.

Problem

When Explorer restarts, the underlying COM interfaces for virtual desktops are destroyed and re-created. Any existing pointers held by pyvda become invalid, leading to RPC_S_SERVER_UNAVAILABLE or RPC_E_DISCONNECTED errors.

Solution

  • Retry Mechanism: Enhanced the _com_retry decorator to attempt the failed operation up to 3 times with an exponential backoff.
  • Automatic Refresh: Upon encountering an RPC error, pyvda now automatically re-initializes its global managers instance, re-acquiring fresh COM pointers.
  • Error Handling: Fixed a bug where RPC errors were incorrectly caught and re-raised as NotImplementedError in _get_object, preventing the retry logic from triggering.
  • Log Cleanup: Downgraded benign RPC_E_CHANGED_MODE warnings (often triggered when multiple libraries try to initialize COM on the same thread with different modes) to debug logs to reduce noise during recovery.

Error Example

_ctypes.COMError: (-2147023174, 'The RPC server is unavailable.', (None, None, None, 0, None))

Steps to Reproduce

  1. Have the latest version of Caster running.
  2. Restart Windows Explorer (e.g., via Task Manager or by running taskkill /f /im explorer.exe && start explorer.exe in a terminal).
  3. Attempt to switch to a specific workspace (e.g., "go work one") using the Caster command.
  4. This calls the following function from castervoice\lib\windows_virtual_desktops.py:
def go_to_desktop_number(n):
    # Helps make sure that the target desktop gets focus
    windll.user32.AllowSetForegroundWindow(ASFW_ANY)
    VirtualDesktop(n).go()
  1. Observe the _ctypes.COMError: (-2147023174, 'The RPC server is unavailable.') because the VirtualDesktop COM object has gone stale following the Explorer restart.

- Implement exponential backoff retry logic in \_com_retry\
- Ensure RPC errors trigger a refresh of the Managers instance
- Prevent RPC errors from being swallowed as NotImplementedError in \_get_object\
- Suppress benign RPC_E_CHANGED_MODE warnings during re-initialization
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant