internal/uevent: handle state divergence
Some checks failed
Test / Flake checks (push) Has been cancelled
Test / Sandbox (push) Has started running
Test / Sandbox (race detector) (push) Has started running
Test / Hakurei (push) Has been cancelled
Test / Hakurei (race detector) (push) Has been cancelled
Test / ShareFS (push) Has been cancelled
Test / Create distribution (push) Has been cancelled
Some checks failed
Test / Flake checks (push) Has been cancelled
Test / Sandbox (push) Has started running
Test / Sandbox (race detector) (push) Has started running
Test / Hakurei (push) Has been cancelled
Test / Hakurei (race detector) (push) Has been cancelled
Test / ShareFS (push) Has been cancelled
Test / Create distribution (push) Has been cancelled
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() }
|
Recoverable interface{ recoverable() }
|
||||||
// Nontrivial is satisfied by errors preferring a JSON encoding.
|
// Nontrivial is satisfied by errors preferring a JSON encoding.
|
||||||
Nontrivial interface{ nontrivial() }
|
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.
|
// Conn represents a NETLINK_KOBJECT_UEVENT socket.
|
||||||
@@ -58,6 +65,18 @@ var (
|
|||||||
ErrBadSocket = errors.New("unexpected socket address")
|
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
|
// BadPortError is returned by [Conn.Consume] upon receiving a message that did
|
||||||
// not come from the kernel.
|
// not come from the kernel.
|
||||||
type BadPortError syscall.SockaddrNetlink
|
type BadPortError syscall.SockaddrNetlink
|
||||||
@@ -84,6 +103,9 @@ func (c *Conn) Consume(ctx context.Context, events chan<- *Message) error {
|
|||||||
for {
|
for {
|
||||||
data, _, from, err := c.conn.Recvmsg(ctx, 0)
|
data, _, from, err := c.conn.Recvmsg(ctx, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if err == syscall.ENOBUFS {
|
||||||
|
return ReceiveBufferError{}
|
||||||
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user