Files
hakurei/internal/uevent/uevent.go
Ophestra 1b48484c16
All checks were successful
Test / Create distribution (push) Successful in 1m15s
Test / Sandbox (push) Successful in 3m2s
Test / Hakurei (push) Successful in 4m15s
Test / ShareFS (push) Successful in 4m16s
Test / Sandbox (race detector) (push) Successful in 5m34s
Test / Hakurei (race detector) (push) Successful in 6m39s
Test / Flake checks (push) Successful in 1m45s
internal/uevent: exclusive socket access
This is a much simplified mutex, since blocking is not required.

Signed-off-by: Ophestra <cat@gensokyo.uk>
2026-03-28 01:01:06 +09:00

51 lines
1.3 KiB
Go

// Package uevent provides userspace client for consuming events from a
// NETLINK_KOBJECT_UEVENT socket, as well as helpers for supplementing
// events received from the kernel.
package uevent
import (
"sync/atomic"
"syscall"
"hakurei.app/internal/netlink"
)
type (
// Recoverable is satisfied by errors that are safe to recover from.
Recoverable interface{ recoverable() }
// Nontrivial is satisfied by errors preferring a JSON encoding.
Nontrivial interface{ nontrivial() }
)
// Conn represents a NETLINK_KOBJECT_UEVENT socket.
type Conn struct {
conn *netlink.Conn
// Whether currently between a call to enterExcl and exitExcl.
excl atomic.Bool
}
// enterExcl must be called entering a critical section that interacts with conn.
func (c *Conn) enterExcl() error {
if !c.excl.CompareAndSwap(false, true) {
return syscall.EAGAIN
}
return nil
}
// exitExcl must be called exiting a critical section that interacts with conn.
func (c *Conn) exitExcl() { c.excl.Store(false) }
// Close closes the underlying socket.
func (c *Conn) Close() error { return c.conn.Close() }
// Dial returns the address of a newly connected [Conn].
func Dial() (*Conn, error) {
// kernel group is hard coded in lib/kobject_uevent.c, undocumented
c, err := netlink.Dial(syscall.NETLINK_KOBJECT_UEVENT, 1)
if err != nil {
return nil, err
}
return &Conn{conn: c}, err
}