supervisor/web_workflow: check the listener socket calls for failure - #64
Closed
mikeysklar wants to merge 3 commits into
Closed
supervisor/web_workflow: check the listener socket calls for failure#64mikeysklar wants to merge 3 commits into
mikeysklar wants to merge 3 commits into
Conversation
check_suite["workflowRun"] is null for check suites that are not attached to a
workflow run, for example one that was deleted or one belonging to an app
integration. get_commit_depth_and_check_suite() dereferenced it
unconditionally:
TypeError: 'NoneType' object is not subscriptable
which fails the scheduler job's Get-last-commit-with-checks step. Skip those
entries rather than indexing into them.
…wrun tools: skip check suites with no workflowRun in ci_changes_per_commit.py
start_web_workflow() created the listening socket, bound it and called
listen() without checking any of them, with an explicit "(Not checking for
failures)" comment on the bind. On a port whose network stack can refuse to
create a socket, the descriptor stays unset and bind() and listen() then run
on -1 and fail with EBADF, but the function still returns true. The caller
takes that as success and installs the background callback, so the supervisor
polls a socket that was never opened and the board can hang before running
code.py. Nothing is ever served, and there is no diagnostic.
Observed on a Silicon Labs SiWx917-DK2605A (BRD2605A) running the zephyr-cp
port, CircuitPython 10.3.0-alpha.4, where socket() returns ENOTCONN until the
interface has an address:
socket() ok=0 num=-1 errno=107 ENOTCONN
bind port 80 -> 9 errno=9 EBADF
listen -> 0 errno=9 closed=1
(returns true)
Return false instead of reporting success, and close the socket if bind or
listen is the step that failed. Note this is not a retry: the next attempt is
the next supervisor_workflow_reset(). Bringing the workflow up once the
interface acquires an address later is a separate change.
This is not specific to that port. adafruit#10054 reports web workflow unreachable
after a watchdog reset on several ESP32 boards, and the attempted fix in
adafruit#10948 moved port 80 from closed to filtered, i.e. bound but never serving,
which is the same end state this produces.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
mikeysklar
force-pushed
the
fix/web-workflow-listener-errors
branch
from
August 17, 2026 22:42
af20412 to
444e5f9
Compare
Owner
Author
|
Superseded by adafruit#11207, which targets |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
supervisor_start_web_workflow()created the listening socket, bound it and calledlisten()without checking any of them, with an explicit// Bind to any ip. (Not checking for failures)comment on the bind. On a port whose network stack can refuse to create a socket, the descriptor stays unset,bind()andlisten()run on -1 and fail withEBADF, and the function still returns true.The caller takes that as success and installs the background callback, so the supervisor polls a socket that was never opened. Nothing is served and there is no diagnostic.
Why
This is shared supervisor code, so it affects every port that has web workflow: espressif, raspberrypi and zephyr-cp.
CIRCUITPY_WEB_WORKFLOW ?= $(CIRCUITPY_WIFI), so atmel-samd, stm and nordic do not compile this file and are unaffected.Not specific to the port where it was found. adafruit#10054 reports web workflow unreachable after a watchdog reset on several ESP32 boards, and the attempted fix in adafruit#10948 moved port 80 from closed to filtered, that is bound but never serving, which is the same end state this produces.
Hardware tested
Silicon Labs SiWx917-DK2605A (BRD2605A), zephyr-cp port, CircuitPython 10.3.0-alpha.4, host on the same LAN. Serial output from the failing case:
With the change the workflow either starts or reports failure, rather than reporting success on a socket that was never opened. Verified serving afterwards:
/cp/version.json200,/fs/401 without credentials and 200 with, PUT 201, GET 200, DELETE 204.Also built for
renesas_ek_ra8d1, a zephyr-cp board CI builds today.Not tested on hardware: espressif or raspberrypi boards, which is where the corroborating reports in adafruit#10054 come from. Worth doing before this goes upstream, and I have an ESP32 and RP2040 targets on a test rig for it.
Scope
Error checking only. Deliberately not a retry: the next attempt is the next
supervisor_workflow_reset(). Bringing the workflow up once the interface acquires an address later is a separate change and is not attempted here.AI assistance
Written with Claude Code. I ran the hardware and the serial output above is from the board, not from a model.