Skip to content

Windows: os.kill(pid, 0) raises SystemError/OSError in gateway/status.py #5760

@Wooklae-cho

Description

@Wooklae-cho

Bug Description

On Windows, os.kill(pid, 0) in gateway/status.py raises SystemError wrapping OSError: [WinError 87] (The parameter is incorrect), causing the gateway to fail to start.

This happens at two locations:

  • Line 267 (acquire_scoped_lock): blocks Telegram platform connection
  • Line 370 (get_running_pid): blocks gateway startup entirely

Environment

  • OS: Windows 11 Pro (10.0.26200)
  • Python: 3.11.12 (installed via uv)
  • Hermes: v0.7.0
  • Install method: PowerShell installer (install.ps1)

Error Trace

File "gateway/status.py", line 370, in get_running_pid
    os.kill(pid, 0)
SystemError: <built-in function kill> returned a result with an exception set
File "gateway/status.py", line 267, in acquire_scoped_lock
    os.kill(existing_pid, 0)
SystemError: <class 'OSError'> returned a result with an exception set

Root Cause

On Windows, os.kill(pid, 0) does not behave the same as on Unix. Instead of raising ProcessLookupError for non-existent processes, it can raise:

  • OSError: [WinError 87] — when the PID is invalid or the process has exited
  • SystemError — when the underlying C function returns an error with an exception set

The current except clause only catches (ProcessLookupError, PermissionError), missing these Windows-specific exceptions.

Fix

--- a/gateway/status.py
+++ b/gateway/status.py
@@ -265,7 +265,7 @@
         if not stale:
             try:
                 os.kill(existing_pid, 0)
-            except (ProcessLookupError, PermissionError):
+            except (ProcessLookupError, PermissionError, OSError, SystemError):
                 stale = True

@@ -368,7 +368,7 @@
     try:
         os.kill(pid, 0)
-    except (ProcessLookupError, PermissionError):
+    except (ProcessLookupError, PermissionError, OSError, SystemError):
         remove_pid_file()
         return None

This is a minimal, safe change — OSError is the parent of ProcessLookupError and PermissionError on all platforms, so it only broadens the catch on Windows where the exception hierarchy differs. SystemError covers the CPython edge case where the C-level kill() wrapper sets an exception but returns a non-standard error.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/gatewayGateway runner, session dispatch, deliverysweeper:implemented-on-mainSweeper: behavior already present on current maintype/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions