Skip to content

[sched] Detect cycles and bound zombie host chain traversal - #7418

Closed
qixuancao wants to merge 1 commit into
BOINC:masterfrom
qixuancao:fix/issue-2433
Closed

qixuancao wants to merge 1 commit into
BOINC:masterfrom
qixuancao:fix/issue-2433

Conversation

@qixuancao

@qixuancao qixuancao commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

authenticate_user() in sched/handle_request.cpp could loop indefinitely if zombie host records form a cycle. This change detects cycles and bounds the number of links followed.

Root cause

When hosts are merged on the web (merge_hosts() in html/inc/host.inc), the old host becomes a "zombie": its userid is set to 0 and rpc_seqno holds the ID of the host it was merged into. When a client sends a zombie's host ID, the scheduler follows these links:

retval = host.lookup_id(g_request->hostid);
while (!retval && host.userid==0) {
    // TODO: check for infinite loop
    retval = host.lookup_id(host.rpc_seqno);
    ...
}

If two zombie host records cross-reference each other (or one references itself), the scheduler loops until CGI timeout while issuing a DB lookup on every iteration.

Fix

  • Track visited host IDs in a small fixed array up to MAX_ZOMBIE_HOST_LINKS (16).
  • Stop immediately if host.rpc_seqno <= 0, if the next ID matches the current host or any previously visited host in the chain, or if MAX_ZOMBIE_HOST_LINKS is reached.
  • Log a MSG_CRITICAL diagnostic when an invalid target (rpc_seqno <= 0), cycle, or excessive chain length is detected, set retval = ERR_DB_NOT_FOUND, reset g_reply->hostid = 0, and fall through to the existing broken zombie chain handling (which creates a new host record).
  • Remove the TODO comment.

Fixes #2433


Summary by cubic

Fixes scheduler stalls when zombie host records form cycles. authenticate_user() follows links from merged host records (userid=0, rpc_seqno → target host), but a self-reference or a cross-reference between two zombies made it loop indefinitely, issuing a DB lookup on every iteration until the CGI timed out.

  • Tracks visited host IDs up to MAX_ZOMBIE_HOST_LINKS (16); stops on self-links, cycles, non-positive target IDs, or the hop limit.
  • Logs an MSG_CRITICAL diagnostic for broken chains and falls through to the existing handling that creates a new host record.

Fixes #2433.

Written for commit c4e1bc7. Summary will update on new commits.

View guided diff

When hosts are merged via the web, the old host record becomes a
"zombie" (userid=0) whose rpc_seqno field holds the ID of the host it
was merged into. authenticate_user() follows these links until it finds
a non-zombie host, but never checks for cycles. If two zombies point at
each other (or one points at itself), the scheduler loops until the CGI
times out, issuing a DB lookup on every iteration.

Track visited host IDs up to MAX_ZOMBIE_HOST_LINKS (16), stop
immediately when a self-link, cycle, non-positive target ID, or hop
limit is reached, log the broken chain, and fall through to the existing
"broken zombie chain" handling which creates a new host record.

Refs: BOINC#2433
Assisted-by: Antigravity:Gemini-4-Argon

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

View guided diff | Re-trigger cubic

@davidpanderson

Copy link
Copy Markdown
Contributor

Way too complex for something that never happens.
Just keep a counter and exit the loop after ~10 times.

@qixuancao

Copy link
Copy Markdown
Contributor Author

Thanks for the feedback! Replaced with a simple 10-iteration counter in #7422.

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.

scheduler: Infinite loop possible

2 participants