internal/uevent: handle state divergence
All checks were successful
Test / Create distribution (push) Successful in 1m16s
Test / Sandbox (push) Successful in 3m9s
Test / Hakurei (push) Successful in 4m13s
Test / ShareFS (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 5m37s
Test / Hakurei (race detector) (push) Successful in 6m47s
Test / Flake checks (push) Successful in 1m25s
All checks were successful
Test / Create distribution (push) Successful in 1m16s
Test / Sandbox (push) Successful in 3m9s
Test / Hakurei (push) Successful in 4m13s
Test / ShareFS (push) Successful in 4m15s
Test / Sandbox (race detector) (push) Successful in 5m37s
Test / Hakurei (race detector) (push) Successful in 6m47s
Test / Flake checks (push) Successful in 1m25s
This requires the caller to arrange for a coldboot to happen, some time after this error is encountered, and to resume event processing. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
@@ -18,6 +18,13 @@ type (
|
||||
Recoverable interface{ recoverable() }
|
||||
// Nontrivial is satisfied by errors preferring a JSON encoding.
|
||||
Nontrivial interface{ nontrivial() }
|
||||
|
||||
// NeedsColdboot is satisfied by errors indicating divergence of local state
|
||||
// from the kernel, usually from lost uevent data.
|
||||
NeedsColdboot interface {
|
||||
Recoverable
|
||||
coldboot()
|
||||
}
|
||||
)
|
||||
|
||||
// Conn represents a NETLINK_KOBJECT_UEVENT socket.
|
||||
@@ -58,6 +65,18 @@ var (
|
||||
ErrBadSocket = errors.New("unexpected socket address")
|
||||
)
|
||||
|
||||
// ReceiveBufferError indicates one or more [Message] being lost due to the
|
||||
// socket receive buffer filling up. This is usually caused by epoll waking the
|
||||
// receiving program up too late.
|
||||
type ReceiveBufferError struct{ _ [0]*ReceiveBufferError }
|
||||
|
||||
var _ NeedsColdboot = ReceiveBufferError{}
|
||||
|
||||
func (ReceiveBufferError) recoverable() {}
|
||||
func (ReceiveBufferError) coldboot() {}
|
||||
func (ReceiveBufferError) Unwrap() error { return syscall.ENOBUFS }
|
||||
func (e ReceiveBufferError) Error() string { return syscall.ENOBUFS.Error() }
|
||||
|
||||
// BadPortError is returned by [Conn.Consume] upon receiving a message that did
|
||||
// not come from the kernel.
|
||||
type BadPortError syscall.SockaddrNetlink
|
||||
@@ -84,6 +103,9 @@ func (c *Conn) Consume(ctx context.Context, events chan<- *Message) error {
|
||||
for {
|
||||
data, _, from, err := c.conn.Recvmsg(ctx, 0)
|
||||
if err != nil {
|
||||
if errors.Is(err, syscall.ENOBUFS) {
|
||||
return ReceiveBufferError{}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user