diff --git a/internal/uevent/uevent.go b/internal/uevent/uevent.go index 6a3ff441..12754f46 100644 --- a/internal/uevent/uevent.go +++ b/internal/uevent/uevent.go @@ -4,6 +4,7 @@ package uevent import ( + "sync/atomic" "syscall" "hakurei.app/internal/netlink" @@ -17,7 +18,23 @@ type ( ) // Conn represents a NETLINK_KOBJECT_UEVENT socket. -type Conn struct{ conn *netlink.Conn } +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() } @@ -29,5 +46,5 @@ func Dial() (*Conn, error) { if err != nil { return nil, err } - return &Conn{c}, err + return &Conn{conn: c}, err }