Skip to content

Commit ff80fce

Browse files
Lukas Geigerclaude
andcommitted
fix: prevent CPU busy-loop when LSP server process dies
When the LSP server crashes, readline() returns b'' (EOF) immediately and forever. The read_loop continued spinning because the outer while condition (process/stdout objects) remained truthy. Now breaks on empty headers (no Content-Length parsed = EOF condition). Adds regression test with 2-second timeout guard to catch reintroduction. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent eaaddb4 commit ff80fce

4 files changed

Lines changed: 31 additions & 34 deletions

File tree

CHANGELOG.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ Format basiert auf [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).
66
## [Unreleased]
77

88
### Hinzugefügt
9-
- README-Discoverability für GitHub/Web-Suche geschärft: englischer SEO-Einstieg,
10-
CodeBox-Namenskollision erklärt, Quickstart und präzisere Suchbegriffe ergänzt.
119
- Headless-Smoke-Test für MainWindow-Instanziierung
1210
- Optionale LSP-Runtime-Tests für `python-lsp-server[all]`:
1311
Diagnostics bei Syntaxfehlern und Completion über `pylsp`.

README.md

Lines changed: 5 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
1-
# CodeBox - local PySide6 desktop code editor
1+
# CodeBox
22

3-
CodeBox is a local-first desktop IDE for Windows developers who want a
4-
lightweight PySide6 code editor with tabs, a project tree, an integrated
5-
terminal, Git helpers, syntax highlighting and Language Server Protocol
6-
diagnostics.
3+
Mehrsprachiger Desktop-Codeeditor auf Basis von PySide6.
4+
Multi-language desktop code editor built with PySide6.
75

8-
Mehrsprachiger Desktop-Codeeditor auf Basis von PySide6. CodeBox ist aus
9-
PythonBox v8 hervorgegangen und bündelt Editor, Projektbaum, Terminal sowie
10-
erste LSP- und API-Grundlagen in einer lokalen IDE.
11-
12-
## Why CodeBox
13-
14-
- Local-first: edit files on your machine without cloud accounts or telemetry.
15-
- PySide6 desktop stack: native Windows app behavior with a small Python codebase.
16-
- Multi-language workflow: Python, JavaScript, TypeScript, C++, Rust, Go and Java.
17-
- LSP-ready: diagnostics and completion can connect to installed language servers.
18-
- Dev-bricks ecosystem: companion to PythonBox and DevCenter for small local tools.
6+
CodeBox ist aus PythonBox v8 hervorgegangen und bündelt Editor, Projektbaum,
7+
Terminal sowie erste LSP- und API-Grundlagen in einer lokalen IDE.
198

209
## Screenshot
2110

@@ -41,14 +30,6 @@ python main.py
4130

4231
Alternativ per Doppelklick auf `start.bat`.
4332

44-
### Quick start
45-
46-
1. Clone `https://github.com/dev-bricks/CodeBox`.
47-
2. Install dependencies with `pip install -r requirements.txt`.
48-
3. Run `python main.py`.
49-
4. Optional: install language servers such as `python-lsp-server[all]` or
50-
`typescript-language-server` for diagnostics and completion.
51-
5233
### Voraussetzungen / Requirements
5334

5435
- Python 3.10+
@@ -105,14 +86,6 @@ config/ Konfigurationsdateien
10586
themes/ QSS-Themes
10687
```
10788

108-
## Discovery keywords
109-
110-
CodeBox is best described as a local PySide6 code editor, Windows desktop IDE,
111-
offline code editor, LSP-enabled Python editor and lightweight multi-language
112-
developer tool. The repository name collides with older projects called
113-
`codebox`, so searches are most precise with `dev-bricks CodeBox`,
114-
`CodeBox PySide6`, `CodeBox LSP editor` or `file-bricks/dev-bricks desktop IDE`.
115-
11689
## Status
11790

11891
Aktueller Stand: `DEV`, Version `0.1.0`

features/lsp_client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,8 @@ def _read_loop(self):
263263

264264
content_length = int(headers.get('Content-Length', 0))
265265
if content_length == 0:
266+
if not headers:
267+
break # EOF — Server-Prozess beendet
266268
continue
267269

268270
# Body lesen

tests/test_lsp_client.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,5 +52,29 @@ def test_unknown_language_is_unavailable(self):
5252
self.assertIsNone(client._resolve_command())
5353

5454

55+
class LSPReadLoopTerminationTests(unittest.TestCase):
56+
def test_read_loop_terminates_on_server_death(self):
57+
"""Regressions-Test: _read_loop darf bei Server-Tod NICHT in einer
58+
Busy-Loop haengen (readline() liefert b'' = EOF endlos)."""
59+
import io
60+
import threading
61+
import types
62+
63+
client = LSPClient("Python")
64+
client.process = types.SimpleNamespace(
65+
stdout=io.BytesIO(b""),
66+
stdin=None,
67+
stderr=None,
68+
)
69+
client._running = True
70+
71+
t = threading.Thread(target=client._read_loop, daemon=True)
72+
t.start()
73+
t.join(timeout=2)
74+
75+
self.assertFalse(t.is_alive(), "read_loop haengt in Busy-Loop (Server-Tod nicht erkannt)")
76+
self.assertFalse(client._running)
77+
78+
5579
if __name__ == "__main__":
5680
unittest.main()

0 commit comments

Comments
 (0)