mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-18 04:49:13 +00:00
fix(starlark): don't crash the pixlet editor's start/stop routes, and honor an operator-set PIXLET_EDITOR_HOST
The AST-based port of #544 onto the api_v3 package split dropped `time` from starlark.py's import list. start_pixlet_editor() and stop_pixlet_editor() both call time.time()/time.sleep() directly, so every start (NameError building `state['started_at']`) and every stop that has to wait out the EXIT trap crashed with a 500. No test caught it because the route's own tests mock subprocess.Popen but never actually invoked it before now. Also carries over #544's later fix that this port branched before: env['PIXLET_EDITOR_HOST'] = '0.0.0.0' unconditionally overrode an operator who had already pinned PIXLET_EDITOR_HOST to loopback, forcing the unauthenticated `pixlet serve` process onto the LAN regardless (CodeQL CWE-1188). Switched to env.setdefault(...), same as api_v3.starlark.py's siblings already do for _pkg-owned names. Both fixes route the shared _pkg.time reference the rest of the package's route modules already use for anything a test might need to patch, rather than a bare `import time` local to this file. Ported the existing regression test from #544 (TestPixletEditorHostDefaultsButDoesNotOverride) onto this branch's module layout (web_interface.blueprints.api_v3.starlark instead of the old monolithic api_v3 module), which is what caught the NameError. Full suite: 4330 passed, 62 skipped, 2 failed -- identical on this branch and on origin/main (missing tzdata package breaks two timezone-alias tests in test_onboarding_checklist.py, unrelated to this change). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -814,8 +814,11 @@ def start_pixlet_editor():
|
||||
env['PIXLET_EDITOR_PORT'] = str(port)
|
||||
env['PIXLET_EDITOR_TIMEOUT'] = str(timeout_s)
|
||||
# A browser reaching this endpoint is remote by definition, so the
|
||||
# session has to listen on more than loopback to be usable at all.
|
||||
env['PIXLET_EDITOR_HOST'] = '0.0.0.0'
|
||||
# session needs to listen on more than loopback to be usable at all --
|
||||
# but only as a *default*. An operator who has already set
|
||||
# PIXLET_EDITOR_HOST (e.g. to keep it loopback-only even from the web
|
||||
# UI) must not have that overridden here.
|
||||
env.setdefault('PIXLET_EDITOR_HOST', '0.0.0.0')
|
||||
|
||||
log_path = Path(tempfile.gettempdir()) / 'ledmatrix_pixlet_editor.log'
|
||||
log_handle = open(log_path, 'w', encoding='utf-8') # noqa: SIM115 - owned by the child
|
||||
@@ -831,10 +834,10 @@ def start_pixlet_editor():
|
||||
finally:
|
||||
log_handle.close()
|
||||
|
||||
now = time.time()
|
||||
now = _pkg.time.time()
|
||||
state = {'pid': process.pid, 'app_id': app_dir.name, 'port': port,
|
||||
'timeout': timeout_s, 'started_at': now, 'deadline': now + timeout_s,
|
||||
'host': '0.0.0.0', 'log': str(log_path)}
|
||||
'host': env['PIXLET_EDITOR_HOST'], 'log': str(log_path)}
|
||||
try:
|
||||
with open(_PIXLET_EDITOR_STATE, 'w', encoding='utf-8') as handle:
|
||||
json.dump(state, handle)
|
||||
@@ -873,9 +876,9 @@ def stop_pixlet_editor():
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
|
||||
# Give the trap a moment to stop pixlet and restart ledmatrix.
|
||||
deadline = time.time() + 10
|
||||
while time.time() < deadline and _pixlet_editor_alive(pid):
|
||||
time.sleep(0.25)
|
||||
deadline = _pkg.time.time() + 10
|
||||
while _pkg.time.time() < deadline and _pixlet_editor_alive(pid):
|
||||
_pkg.time.sleep(0.25)
|
||||
|
||||
if _pixlet_editor_alive(pid):
|
||||
logger.warning('Editor session %s ignored SIGTERM; sending SIGKILL. The display '
|
||||
|
||||
Reference in New Issue
Block a user