Skip to content

fix(orchestrator): do not register signal handlers off the main thread - #12

Merged
thezoid merged 2 commits into
masterfrom
fix/signal-handler-main-thread
Aug 2, 2026
Merged

fix(orchestrator): do not register signal handlers off the main thread#12
thezoid merged 2 commits into
masterfrom
fix/signal-handler-main-thread

Conversation

@thezoid

@thezoid thezoid commented Aug 1, 2026

Copy link
Copy Markdown
Owner

No description provided.

BotService.start() runs async_main in a daemon thread, which is the web
dashboard's Start Bot path. Signal disposition is main-thread-only in
CPython, so _register_signals raised ValueError as async_main's fifth
statement and the bot loop died before plugin setup -- while
POST /api/bot/start still returned 200 and the UI showed no error.

On Windows the ValueError comes from the signal.signal() fallback after
add_signal_handler raises NotImplementedError; on POSIX it comes from
add_signal_handler itself via signal.set_wakeup_fd, which the existing
NotImplementedError handler does not catch. A main-thread guard covers
both. The threaded path does not need handlers: BotService.stop()
already cancels the root task cooperatively.

Found by live UAT (27-HV-2, 29-HV-2), deferred as debt since v4.1.
@thezoid
thezoid force-pushed the fix/signal-handler-main-thread branch from 3c5c896 to 3f27a2d Compare August 1, 2026 23:40
@thezoid
thezoid merged commit 36f75c7 into master Aug 2, 2026
6 checks passed
thezoid added a commit that referenced this pull request Aug 2, 2026
13 PASS, 1 FAIL, 5 BLOCKED, 2 PARTIAL from a live browser session plus
live GitHub API checks.

The FAIL is 29-HV-2: dashboard Start Bot never runs the bot. Root-caused
to _register_signals raising ValueError off the main thread; fixed in
PR #12. 27-HV-2 and 28-HV-1 are downstream of the same defect.

31-HV-1 and 31-HV-2 flipped to PASS after the operator widened the
Actions allowlist and re-enabled CodeQL: gitleaks and CodeQL both ran
green for the first time. 32-HV-1/2/3 and REG-01 also closed.

Records five documentation drifts found in passing: the stale
"four sections" count (now eight), the `python main.py` launcher (starts
no HTTP server), the window.EventSource reload recipe (cannot work), the
hardcoded banner hex (now themed tokens), and the cold-load theme default
(dark, not light).
thezoid added a commit that referenced this pull request Aug 2, 2026
- PR #12 merged as merge commit 36f75c7; MAIN-05 satisfied
- master advanced e98ec83 -> 36f75c7
- Record the update-branch head move 3f27a2d -> b1d7b8f (strict mode)
- Record the file-scope deviation from the planning-time expectation
thezoid added a commit that referenced this pull request Aug 2, 2026
- Record actual BASE_SHA e98ec83, post-#12 master 36f75c7, PR #12 head 3f27a2d
- MAIN-05 and MAIN-06 satisfied; no force op, no --admin, protection unchanged
thezoid added a commit that referenced this pull request Aug 2, 2026
Resolves PR #11's two conflicts by union, per the locked rules in
36-CONTEXT.md "Conflict Resolution and PR Disposition".

requirements.txt (content conflict), three decided pins:
- httpx==0.28.1        kept from master (MAIN-02 exists to stop this drop)
- cryptography==49.0.0 taken from branch (master had 44.0.2)
- pydantic-settings[yaml]==2.14.2 taken from branch (master had 2.14.0)
Every other pin was already byte-identical on both sides. 17 lines total,
alphabetical order preserved, one line each, pip dry-run resolves clean.

.github/dependabot.yml (add/add conflict), union of both sides:
- from master: groups.minor-and-patch update-types [minor, patch] on BOTH
  the pip and github-actions ecosystems (this is why PR #15 exists)
- from branch: labels, schedule.day "monday", pip open-pull-requests-limit 10
- github-actions open-pull-requests-limit stays 5, untouched by either diff

Auto-merged and verified, not assumed:
- .github/workflows/ci.yml takes master's Install step (requirements.txt
  before the editable install) and keeps SHOPBOT_DATA_DIR at step level,
  never job level, while retaining the branch's newer action pins
- core/orchestrator.py carries PR #12's main-thread guard in _register_signals
- tests/test_signal_registration_thread.py added from master (PR #12)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant