-
-
Notifications
You must be signed in to change notification settings - Fork 21
fix(daemon): identify our daemon on Windows via CIM, not ps #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1045,3 +1045,56 @@ def test_release_pidfile_still_cleans_its_own_file(monkeypatch, tmp_path: Path): | |
| assert _d._acquire_pidfile() is True | ||
| _d._release_pidfile() | ||
| assert not _d.pid_path().exists() | ||
|
|
||
|
|
||
| def test_windows_identity_uses_cim_not_ps(monkeypatch): | ||
| """On Windows there is no /proc, and a Git-Bash `ps` on PATH only lists | ||
| MSYS processes — a natively spawned daemon reads as gone, so `cs daemon | ||
| stop` refuses to stop it and the drift-kill guard never restarts it onto | ||
| upgraded code.""" | ||
| import subprocess as _sp | ||
|
|
||
| calls = [] | ||
|
|
||
| def fake_run(cmd, **kw): | ||
| calls.append(cmd[0]) | ||
| if cmd[0] == "ps": | ||
| raise AssertionError("ps must not be consulted on win32") | ||
| return _sp.CompletedProcess( | ||
| cmd, 0, | ||
| stdout=('"C:\Python\python.exe" -m claude_statusbar.cli ' | ||
| 'daemon _run --render-interval 1.0\n'), | ||
| stderr="", | ||
| ) | ||
|
Comment on lines
+1063
to
+1068
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win 🧩 Analysis chain🏁 Script executed: set -euo pipefail
# Show the relevant sections with line numbers
sed -n '1058,1072p;1078,1088p' tests/test_daemon.py
# Probe Python's handling of the exact string literals used in the review comment
python3 - <<'PY'
import warnings
snippets = [
'"C:\\Python\\python.exe" -m claude_statusbar.cli daemon _run --render-interval 1.0\n',
"C:\\Windows\\explorer.exe\n",
'"C:\Python\python.exe" -m claude_statusbar.cli daemon _run --render-interval 1.0\n',
"C:\Windows\explorer.exe\n",
]
for s in snippets:
print("SNIPPET:", repr(s))
try:
compile(f"x = {s!r}", "<snippet>", "exec")
print("compile: ok")
except Exception as e:
print("compile:", type(e).__name__, e)
# Specifically compile literal source containing invalid escapes to see warnings/errors.
sources = [
'x = "C:\\Python\\python.exe" -m claude_statusbar.cli daemon _run --render-interval 1.0\n',
'x = "C:\\Windows\\explorer.exe\n"',
'x = "C:\\Python\\python.exe"\n',
'x = "C:\\Windows\\explorer.exe"\n',
]
for src in sources:
print("\nSOURCE:", src.encode("unicode_escape").decode())
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
try:
compile(src, "<src>", "exec")
print("compile: ok")
except Exception as e:
print("compile:", type(e).__name__, e)
for item in w:
print("warning:", item.category.__name__, str(item.message))
PYRepository: leeguooooo/claude-code-usage-bar Length of output: 1877 🏁 Script executed: set -euo pipefail
printf '\n-- targeted source --\n'
nl -ba tests/test_daemon.py | sed -n '1058,1072p;1078,1088p'
printf '\n-- python probe --\n'
python3 - <<'PY'
import warnings
# Build the exact source text without letting this script's parser interpret it.
good1 = '"C:\\\\Python\\\\python.exe" -m claude_statusbar.cli daemon _run --render-interval 1.0\n'
good2 = 'C:\\\\Windows\\\\explorer.exe\n'
bad1 = '"C:\\Python\\python.exe" -m claude_statusbar.cli daemon _run --render-interval 1.0\n'
bad2 = 'C:\\Windows\\explorer.exe\n'
for label, text in [('good1', good1), ('good2', good2), ('bad1', bad1), ('bad2', bad2)]:
print(label, repr(text))
src = 'x = ' + repr(text) + '\n'
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
try:
compile(src, '<src>', 'exec')
print(' compile: ok')
except Exception as e:
print(' compile:', type(e).__name__, e)
for item in w:
print(' warning:', item.category.__name__, str(item.message))
# Compile exact raw source code containing invalid escapes
raw_sources = [
'x = "C:\\Python\\python.exe" -m claude_statusbar.cli daemon _run --render-interval 1.0\n',
'x = "C:\\Windows\\explorer.exe\\n"\n',
'x = "C:\\Python\\python.exe"\n',
'x = "C:\\Windows\\explorer.exe"\n',
]
for src in raw_sources:
print('\nRAW SRC:', src.encode('unicode_escape').decode())
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
try:
compile(src, '<raw>', 'exec')
print(' compile: ok')
except Exception as e:
print(' compile:', type(e).__name__, e)
for item in w:
print(' warning:', item.category.__name__, str(item.message))
PYRepository: leeguooooo/claude-code-usage-bar Length of output: 233 🏁 Script executed: set -euo pipefail
python3 - <<'PY'
from pathlib import Path
path = Path("tests/test_daemon.py")
lines = path.read_text().splitlines()
for n in [1063, 1064, 1065, 1066, 1067, 1068, 1082, 1083, 1084, 1085]:
print(f"{n}: {lines[n-1]!r}")
PY
printf '\n-- warning-mode probe --\n'
python3 -Wd - <<'PY'
s1 = "C:\Python\python.exe"
s2 = "C:\Windows\explorer.exe"
print(repr(s1))
print(repr(s2))
PYRepository: leeguooooo/claude-code-usage-bar Length of output: 819 Escape the Windows path literals. 🤖 Prompt for AI Agents |
||
|
|
||
| monkeypatch.setattr(sys, "platform", "win32") | ||
| monkeypatch.setattr(_sp, "run", fake_run) | ||
|
|
||
| assert _d._process_is_our_daemon(4242) is True | ||
| assert calls and calls[0] in ("powershell", "pwsh") | ||
|
|
||
|
|
||
| def test_windows_identity_false_when_pid_is_someone_else(monkeypatch): | ||
| import subprocess as _sp | ||
|
|
||
| monkeypatch.setattr(sys, "platform", "win32") | ||
| monkeypatch.setattr( | ||
| _sp, "run", | ||
| lambda cmd, **kw: _sp.CompletedProcess( | ||
| cmd, 0, stdout="C:\Windows\explorer.exe\n", stderr=""), | ||
| ) | ||
|
|
||
| assert _d._process_is_our_daemon(4242) is False | ||
|
|
||
|
|
||
| def test_windows_identity_false_when_no_shell_available(monkeypatch): | ||
| """No powershell and no pwsh — stay conservative, never SIGTERM.""" | ||
| import subprocess as _sp | ||
|
|
||
| monkeypatch.setattr(sys, "platform", "win32") | ||
| monkeypatch.setattr( | ||
| _sp, "run", | ||
| lambda cmd, **kw: (_ for _ in ()).throw(FileNotFoundError(cmd[0])), | ||
| ) | ||
|
|
||
| assert _d._process_is_our_daemon(4242) is False | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚀 Performance & Scalability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 170
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 17063
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 6736
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 50391
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 6056
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 10203
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 2643
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 4514
🏁 Script executed:
Repository: leeguooooo/claude-code-usage-bar
Length of output: 1628
Keep the Windows CIM probe off the
cs renderfallback path.spawn_if_dead()is still reached fromrender_thin._spawn_daemon_async(), so a stale or missing daemon can makecs renderblock on_process_is_our_daemon()before falling back inline. On Windows that can add up to 16s ofpowershell/pwshtimeout latency to a status-line tick; reserve the identity check for explicit daemon-management commands, or skip it on this render-triggered path.🤖 Prompt for AI Agents