Skip to content

fix(manager): surface liveness subscribe failures instead of reporting success - #778

Open
iaroslav-reflection wants to merge 1 commit into
containerd:mainfrom
iaroslav-reflection:fix/liveness-subscribe-errors
Open

fix(manager): surface liveness subscribe failures instead of reporting success#778
iaroslav-reflection wants to merge 1 commit into
containerd:mainfrom
iaroslav-reflection:fix/liveness-subscribe-errors

Conversation

@iaroslav-reflection

Copy link
Copy Markdown
Contributor

Subscribe armed the epoll watch inside a rawConn.Control callback that assigned failures to the named error return — which the enclosing err = rawConn.Control(...) then overwrote with Control's own nil result. A failed SetNonblock/EpollCtl still logged "Subscribe daemon ... liveness event" and returned nil.

flowchart LR
    A["err = rawConn.Control(closure)"] --> B["closure: EpollCtl fails → sets err"]
    B --> C["Control returns nil →<br/>err overwritten"]
    C --> D["caller believes daemon is monitored"]
    D --> E["💥 nydusd dies → no death event →<br/>no restart/failover → ENOTCONN,<br/>logs claim monitoring was active"]
Loading

The daemon was never added to the epoll interest list, so its death produces no event and restart/failover recovery never starts — with nothing in the logs explaining why. The dialed unix connection also leaked on this path.

Add a controlFD helper returning the first error from either Control or the callback, make Subscribe all-or-nothing (close the connection and register nothing on failure), and use the helper in unsubscribe, where an EPOLL_CTL_DEL failure previously left a stale fd entry in the interest set that could collide with a future subscription reusing the same fd number.

@iaroslav-reflection

Copy link
Copy Markdown
Contributor Author

@imeoer @Zephyrcf PTAL

@iaroslav-reflection
iaroslav-reflection force-pushed the fix/liveness-subscribe-errors branch from 2e42d0e to a2664b9 Compare July 20, 2026 16:49
@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 52.17391% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 26.05%. Comparing base (d16caad) to head (3479119).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
pkg/manager/monitor.go 52.17% 8 Missing and 3 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main     #778      +/-   ##
==========================================
+ Coverage   25.42%   26.05%   +0.63%     
==========================================
  Files         133      133              
  Lines       12639    12719      +80     
==========================================
+ Hits         3213     3314     +101     
+ Misses       9036     8998      -38     
- Partials      390      407      +17     
Files with missing lines Coverage Δ
pkg/manager/monitor.go 64.60% <52.17%> (+1.74%) ⬆️

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Zephyrcf Zephyrcf 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.

LGTM, thanks!

Comment thread pkg/manager/monitor.go Outdated
if closeErr := uc.Close(); closeErr != nil {
log.L.WithError(closeErr).Warnf("close liveness connection for daemon %s", id)
}
return

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.

Suggested change
return
return err

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, applied!

…g success

livenessMonitor.Subscribe armed the epoll subscription inside a
syscall.RawConn.Control callback that assigned failures to the function's
named error return -- which the enclosing `err = rawConn.Control(...)`
statement then overwrote with Control's own nil result. A failed
unix.SetNonblock or unix.EpollCtl was therefore logged, "Subscribe daemon
... liveness event" was still printed, and Subscribe returned nil.

The caller then believes the daemon is monitored when it was never added
to the epoll interest list: when that nydusd later dies no death event
fires, so restart/failover recovery never starts and the daemon's
containers are left with dead FUSE mounts -- with nothing in the logs
explaining why. The dialed unix connection also leaked on this path.

Introduce a controlFD helper that returns the first error from either
Control itself or the callback, make Subscribe all-or-nothing (close the
connection and register nothing on failure), and use the same helper in
unsubscribe, where an EPOLL_CTL_DEL failure previously left a stale fd
entry in the interest set that could collide with a future subscription
reusing the same fd number.

Signed-off-by: Iaroslav Geraskin <iaroslav@reflection.ai>
@iaroslav-reflection
iaroslav-reflection force-pushed the fix/liveness-subscribe-errors branch from a2664b9 to 3479119 Compare July 21, 2026 16:50
@iaroslav-reflection

Copy link
Copy Markdown
Contributor Author

@imeoer approved by @Zephyrcf, good to merge? The e2e failure is the race flake fixed in #781.

@iaroslav-reflection

Copy link
Copy Markdown
Contributor Author

@imeoer ping — approved since July, good to merge?

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.

2 participants