TencentCloud / TencentCloud/Octop
[bug] Windows 上第二个用户打开工作台浏览器失败:Chrome did not start on localhost:9223
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4.2k
- Forks
- 459
- Avg merge
- 8h 36m
- Merged PRs (30d)
- 228
Description
问题
Windows 上第二个用户打开工作台(Dashboard)浏览器时失败:
failed to attach browser profile 'user-2':
Chrome did not start on localhost:9223 after 20 attempts
日志中伴随:
WARNING harness_browser.cdp.launch_prep — Browser profile
...\browser-profiles\user-2 is not Chrome-safe;
using \tmp\harness-browser-profiles-0\user-2 (BROWSER_USE_PROFILES_DIR)
环境
- Windows 10/11,普通用户(非提权)
- Octop 1.0.0(harness-browser 0.7.8)
- 两个账号:user-1 正常,user-2 必失败
- 注:本机为管理员且已提权时问题同样复现,非权限问题
根因
harness_browser/cdp/launch_prep.py 两处平台缺陷:
_probe_writable()在 Windows 上也创建 symlink。Windows 普通用户没有
SeCreateSymbolicLinkPrivilege,探测必然OSError→ 返回 False →
ensure_profile_writable()误判 profile 不可用并触发迁移。_alt_profiles_root()返回Path("/tmp/harness-browser-profiles-{uid}"),
在 Windows 上得到无盘符相对路径\tmp\...,Chrome 无法将其作为
--user-data-dir,因此启动失败。
另(可另行讨论,本 PR 未改):ensure_profile_writable() 迁移时会写入进程级
os.environ["BROWSER_USE_PROFILES_DIR"] 与 harness_browser.settings.profiles_dir,
会污染同一进程内后续其他用户的启动。
旁证(内部不一致):同一依赖链上的 octop/infra/browser/setup.py 中
_probe_dir_writable() 已明确在非 Linux 跳过 symlink 探测,且
_relocated_profiles_root_for_uid() 在非 Linux 使用 tempfile.gettempdir(),
说明该写法是既定意图,launch_prep.py 未同步。
修复
_probe_writable():仅在os.name == "posix"时执行 symlink 探测;_alt_profiles_root():非 POSIX 返回
Path(tempfile.gettempdir()) / f"harness-browser-profiles-{USERNAME or USER or 'default'}";- 新增
import tempfile。
POSIX 行为完全不变(仍走 /tmp/harness-browser-profiles-<uid>,Linux 下是空操作)。
验证
git apply --check通过;应用后与预期文件字节级一致- Windows 实测:修复前 user-2 报
Chrome did not start on localhost:9223;
修复后两账号并发正常,Chrome 分别以
--user-data-dir=...\browser-profiles\user-1(9222)与...\user-2(9223)运行,
日志不再出现not Chrome-safe - Linux 回归:
_probe_writable仍执行 symlink 探测(调用次数 1→1),
_alt_profiles_root()输出不变
补丁(可直接应用,仅供定位参考):
# Fix: Windows CDP profile relocation to an invalid drive-relative path
#
# packages/harness_browser/cdp/launch_prep.py
# 1. _probe_writable(): skip the symlink probe on Windows. Normal Windows
# users lack SeCreateSymbolicLinkPrivilege, so the probe always failed and
# forced a bogus 'profile is not Chrome-safe' relocation.
# 2. _alt_profiles_root(): on Windows return an absolute temp path instead of
# Path('/tmp/...'), which becomes a drive-relative '\tmp\...' that Chrome
# cannot use as --user-data-dir.
#
# Symptom: 'failed to attach browser profile user-2: Chrome did not start on
# localhost:9223 after 20 attempts' when a second user opens the workbench
# browser on Windows.
#
# Apply with: patch -p1 -d <repo-root> < octop-browser-win-fix.patch
# or: git apply -p1 octop-browser-win-fix.patch
#
# Platform notes:
# * POSIX (Linux/macOS) behaviour is UNCHANGED: the symlink probe still runs
# and _alt_profiles_root() still returns /tmp/harness-browser-profiles-<uid>.
# The patch is a no-op there; it is only needed on Windows (including
# Windows Server, e.g. when Octop runs under a service account that cannot
# create symlinks).
# * Generated against harness-browser 0.7.8 (the version bundled with
# Octop 1.0.0). Verify the file still matches before applying; if the
# upstream file moved, re-apply the 3 edits manually.
--- a/packages/harness_browser/cdp/launch_prep.py
+++ b/packages/harness_browser/cdp/launch_prep.py
@@ -20,6 +20,7 @@
import shutil
import subprocess
import sys
+import tempfile
import time
from pathlib import Path
@@ -69,18 +70,31 @@
probe = directory / f".harness-write-{os.getpid()}"
probe.write_text("ok", encoding="utf-8")
probe.unlink()
- # Chrome's ProcessSingleton creates a symlink; probe that too.
- link = directory / f".harness-link-{os.getpid()}"
- link.symlink_to("probe-target")
- link.unlink()
+ # Chrome's ProcessSingleton creates a symlink; probe that too on
+ # POSIX. Windows normal users lack SeCreateSymbolicLinkPrivilege, so
+ # a failed symlink probe there does not mean Chrome cannot use the
+ # directory (and must not force a relocation).
+ if os.name != "nt":
+ link = directory / f".harness-link-{os.getpid()}"
+ link.symlink_to("probe-target")
+ link.unlink()
return True
except OSError:
return False
def _alt_profiles_root() -> Path:
- uid = os.getuid() if hasattr(os, "getuid") else 0
- return Path(f"/tmp/harness-browser-profiles-{uid}")
+ getuid = getattr(os, "getuid", None)
+ if callable(getuid):
+ return Path(f"/tmp/harness-browser-profiles-{getuid()}")
+ # Windows: never use a drive-relative ``\tmp\...`` path (Chrome resolves
+ # that against its own working directory). Use an absolute temp root and a
+ # stable per-user token so relocated profiles survive restarts.
+ token = (
+ (os.environ.get("USERNAME") or os.environ.get("USER") or "default").strip()
+ or "default"
+ )
+ return Path(tempfile.gettempdir()) / f"harness-browser-profiles-{token}"
def _under_root_home(path: Path) -> bool:
根因在 harness-browser 0.7.8(Octop 仅通过依赖引入),请帮忙转到上游修复; harness-browser 尚未开源,补丁供定位参考
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with packages/harness_browser/cdp/launch_prep.py, focusing on _probe_writable() and _alt_profiles_root(); compare the related logic in octop/infra/browser/setup.py. Verify the Windows profile paths and POSIX regression behavior described in the issue, then coordinate the fix with the upstream harness-browser project because its source is not included here.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- devtools
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 38/100