Skip to content

Windows: launch crashes on registry save (os.rename) and every command crashes (os.kill(pid, 0)) #2

Description

@omerlefaruk

Two Windows-only crashes prevent the CLI from working at all on Windows (verified on Win 11, chrome-agent 0.5.7, Python 3.13, Chrome 151).

Bug 1: launch fails with FileExistsError on every launch after the first

registry.py:83 (_save_registry) uses os.rename(tmp_path, registry_path) for atomic save. On POSIX rename(2) overwrites the destination; on Windows it does not — it raises FileExistsError: [WinError 183] Cannot create a file when that file already exists whenever registry.json already exists (i.e. every launch after the first).

File "chrome_agent/registry.py", line 83, in _save_registry
    os.rename(tmp_path, registry_path)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'C:\tmp\chrome-agent\registry.json.tmp' -> 'C:\tmp\chrome-agent\registry.json'

Fix: os.replace(tmp_path, registry_path) — atomic overwrite on both platforms.

Worse, the crash happens after Chrome was launched, so the browser process is orphaned with no registry entry — cleanup can't find it.

Bug 2: every command (status, one-shot, etc.) crashes in the liveness check

utils.py process_is_running / process_is_ours use os.kill(pid, 0) as an existence probe — a POSIX signal-0 idiom. On Windows this raises OSError: [WinError 87] The parameter is incorrect instead of returning, so every command that enumerates the registry dies:

File "chrome_agent/utils.py", line 42, in process_is_ours
    os.kill(pid, 0)
OSError: [WinError 87] The parameter is incorrect

Also process_start_time can only read /proc/<pid>/stat or ps -o lstart= — both absent on Windows — so the PID-recycling protection silently degrades to None.

Fix: probe via OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION) + GetExitCodeProcess (STILL_ACTIVE), and derive the start token from the GetProcessTimes creation FILETIME. I verified this ctypes approach locally and it restores full functionality.

Tested working after local patches

  • launch / status / stop / cleanup
  • one-shot Runtime.evaluate, Page.navigate, Page.captureScreenshot
  • attach event streaming (Page.frameNavigated, Page.loadEventFired)
  • attach auto-exits when the instance is retired

Happy to open a PR with both fixes (both are small and stdlib-only).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions