Skip to content

Commit 562b4fb

Browse files
committed
Replace github.com/s-urbaniak/uevent.go with github.com/pilebones/go-udev/netlink
github.com/s-urbaniak/uevent.go is unable to handle errors from udev netlik listener. It just panics. Issue #155
1 parent 390d105 commit 562b4fb

File tree

4 files changed

+59
-53
lines changed

4 files changed

+59
-53
lines changed

Diff for: go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ require (
88
github.com/anatol/luks.go v0.0.0-20211210165108-5d9a15b4f614
99
github.com/anatol/smart.go v0.0.0-20220218195151-5ee9e8fa73f0
1010
github.com/anatol/tang.go v0.0.0-20220401181244-14a5a12378ca
11-
github.com/anatol/uevent.go v1.0.1-0.20210811163347-3e166d38c549
1211
github.com/anatol/vmtest v0.0.0-20211215032353-afd7b1dd38ef
1312
github.com/cavaliergopher/cpio v1.0.1
1413
github.com/google/go-tpm v0.3.3
1514
github.com/google/renameio v1.0.1
1615
github.com/insomniacslk/dhcp v0.0.0-20220119180841-3c283ff8b7dd
1716
github.com/jessevdk/go-flags v1.5.0
1817
github.com/klauspost/compress v1.15.1
18+
github.com/pilebones/go-udev v0.9.0
1919
github.com/stretchr/testify v1.7.1
2020
github.com/ulikunitz/xz v0.5.10
2121
github.com/vishvananda/netlink v1.1.0

Diff for: go.sum

+4-3
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ github.com/anatol/smart.go v0.0.0-20220218195151-5ee9e8fa73f0 h1:rnURfQKi7StDt+W
1313
github.com/anatol/smart.go v0.0.0-20220218195151-5ee9e8fa73f0/go.mod h1:mPog5NmM5znyLbUO9WQPJ4xQdVtuHPptPavY0055POc=
1414
github.com/anatol/tang.go v0.0.0-20220401181244-14a5a12378ca h1:60FgDd7iZj00Ggcm2VLkzRAuUSAMZrHqDcUqYApSG5A=
1515
github.com/anatol/tang.go v0.0.0-20220401181244-14a5a12378ca/go.mod h1:eehwvW8/vkT20kR75KYthbNZYCXyQVt4T6XGSLplJQ0=
16-
github.com/anatol/uevent.go v1.0.1-0.20210811163347-3e166d38c549 h1:CPuCjtWK5UI9KQPDhylGHfZe7Pp8j58WK7i3wpLemA0=
17-
github.com/anatol/uevent.go v1.0.1-0.20210811163347-3e166d38c549/go.mod h1:yO7hm0VhhOujsh+j0nn8ExPhAqIJh50MZOcKetKhAPA=
1816
github.com/anatol/vmtest v0.0.0-20211215032353-afd7b1dd38ef h1:YQzm9r8/ArTsQ6C3/h+w4Dz5dfkYkQbK/3ETLWW2i7Q=
1917
github.com/anatol/vmtest v0.0.0-20211215032353-afd7b1dd38ef/go.mod h1:JiDFhD1zjgMx9ONsHhhucGwMvCLrJMl/yu/l5qP4XFw=
2018
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -108,8 +106,9 @@ github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583
108106
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
109107
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
110108
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
111-
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
112109
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
110+
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
111+
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
113112
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
114113
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
115114
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -142,6 +141,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
142141
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
143142
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
144143
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
144+
github.com/pilebones/go-udev v0.9.0 h1:N1uEO/SxUwtIctc0WLU0t69JeBxIYEYnj8lT/Nabl9Q=
145+
github.com/pilebones/go-udev v0.9.0/go.mod h1:T2eI2tUSK0hA2WS5QLjXJUfQkluZQu+18Cqvem3CaXI=
145146
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
146147
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
147148
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=

Diff for: init/main.go

+2
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,8 @@ func switchRoot() error {
616616

617617
// Cleanup the state before handing off the machine to the new init
618618
func cleanup() {
619+
close(udevQuitLoop)
620+
udevConn.Close()
619621
shutdownNetwork()
620622
}
621623

Diff for: init/udev.go

+52-49
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package main
22

33
import (
44
"fmt"
5-
"io"
65
"net"
76
"os"
87
"path/filepath"
@@ -11,14 +10,14 @@ import (
1110
"strings"
1211

1312
"github.com/anatol/devmapper.go"
14-
"github.com/anatol/uevent.go"
13+
"github.com/pilebones/go-udev/netlink"
1514
"golang.org/x/sys/unix"
1615
)
1716

1817
// validDmEvent checks whether this udev event has correct flags.
1918
// This is similar to checks done by /usr/lib/udev/rules.d/10-dm.rules udev rules.
20-
func validDmEvent(ev *uevent.Uevent) bool {
21-
dmCookie := ev.Vars["DM_COOKIE"]
19+
func validDmEvent(ev netlink.UEvent) bool {
20+
dmCookie := ev.Env["DM_COOKIE"]
2221
if dmCookie == "" {
2322
info("udev event does not contain DM_COOKIE")
2423
return false
@@ -63,57 +62,61 @@ func validDmEvent(ev *uevent.Uevent) bool {
6362
return true
6463
}
6564

66-
var udevReader io.ReadCloser
65+
var (
66+
udevQuitLoop chan struct{}
67+
udevConn *netlink.UEventConn
68+
)
6769

6870
func udevListener() error {
69-
defer func() {
70-
// uevent.NewDecoder uses bufio.ReadString() that is blocking. If we try to close the underlying udev file descriptor
71-
// while bufio tries to read from it then bufio panics. See issues #22, #31 and #153
72-
// There is no clear way to prevent the panic so we just recover from it here and then safely exit the goroutine.
73-
if r := recover(); r != nil {
74-
warning("recovered udevListener panic: %v", r)
75-
}
76-
}()
77-
78-
var err error
79-
udevReader, err = uevent.NewReader()
80-
if err != nil {
81-
return err
71+
udevConn = new(netlink.UEventConn)
72+
if err := udevConn.Connect(netlink.KernelEvent); err != nil {
73+
return fmt.Errorf("unable to connect to Netlink Kobject UEvent socket")
8274
}
83-
defer udevReader.Close()
75+
defer udevConn.Close()
8476

85-
dec := uevent.NewDecoder(udevReader)
77+
queue := make(chan netlink.UEvent)
78+
errors := make(chan error)
79+
udevQuitLoop = udevConn.Monitor(queue, errors, nil)
8680

81+
exit:
8782
for {
88-
ev, err := dec.Decode()
89-
if err == io.EOF {
90-
// EOF is returned if uevent reader is closed concurrently
91-
return nil
92-
}
93-
if err != nil {
94-
return err
95-
}
96-
debug("udev event %+v", *ev)
97-
98-
// TODO: run each udev in a separate goroutine
99-
if modalias, ok := ev.Vars["MODALIAS"]; ok {
100-
go func() { check(loadModalias(modalias)) }()
101-
} else if ev.Subsystem == "block" {
102-
go func() { check(handleBlockDeviceUevent(ev)) }()
103-
} else if ev.Subsystem == "net" {
104-
go func() { check(handleNetworkUevent(ev)) }()
105-
} else if ev.Subsystem == "hidraw" && ev.Action == "add" {
106-
go func() { hidrawDevices <- ev.Vars["DEVNAME"] }()
83+
select {
84+
case ev, ok := <-queue:
85+
if !ok {
86+
break exit
87+
}
88+
handleUdevEvent(ev)
89+
case err, ok := <-errors:
90+
if !ok {
91+
break exit
92+
}
93+
warning("udev: %+v", err)
10794
}
10895
}
96+
97+
return nil
98+
}
99+
100+
func handleUdevEvent(ev netlink.UEvent) {
101+
debug("udev event: %+v", ev)
102+
103+
if modalias, ok := ev.Env["MODALIAS"]; ok {
104+
go func() { check(loadModalias(modalias)) }()
105+
} else if ev.Env["SUBSYSTEM"] == "block" {
106+
go func() { check(handleBlockDeviceUevent(ev)) }()
107+
} else if ev.Env["SUBSYSTEM"] == "net" {
108+
go func() { check(handleNetworkUevent(ev)) }()
109+
} else if ev.Env["SUBSYSTEM"] == "hidraw" && ev.Action == "add" {
110+
go func() { hidrawDevices <- ev.Env["DEVNAME"] }()
111+
}
109112
}
110113

111-
func handleNetworkUevent(ev *uevent.Uevent) error {
114+
func handleNetworkUevent(ev netlink.UEvent) error {
112115
if ev.Action != "add" {
113116
return nil
114117
}
115118

116-
ifname := ev.Vars["INTERFACE"]
119+
ifname := ev.Env["INTERFACE"]
117120
if ifname == "lo" {
118121
return nil
119122
}
@@ -140,8 +143,8 @@ func handleNetworkUevent(ev *uevent.Uevent) error {
140143

141144
var dmNameRe = regexp.MustCompile(`dm-\d+`)
142145

143-
func handleBlockDeviceUevent(ev *uevent.Uevent) error {
144-
devName := ev.Vars["DEVNAME"]
146+
func handleBlockDeviceUevent(ev netlink.UEvent) error {
147+
devName := ev.Env["DEVNAME"]
145148

146149
if dmNameRe.MatchString(devName) {
147150
// mapper devices should not be added on "add" uevent
@@ -159,10 +162,10 @@ func handleBlockDeviceUevent(ev *uevent.Uevent) error {
159162

160163
devPath := "/dev/" + devName
161164

162-
isPartition := ev.Vars["DEVTYPE"] == "partition"
165+
isPartition := ev.Env["DEVTYPE"] == "partition"
163166
if isPartition {
164167
// if this device represents a partition inside a table (like GPT) then wait till the table is processed
165-
parts := strings.Split(ev.Devpath, "/")
168+
parts := strings.Split(ev.KObj, "/")
166169
tablePath := "/dev/" + parts[len(parts)-2]
167170
waitForDeviceToProcess(tablePath)
168171
}
@@ -173,14 +176,14 @@ func handleBlockDeviceUevent(ev *uevent.Uevent) error {
173176
// handleMapperDeviceUevent handles device mapper related uevent
174177
// if udev event is valid then it return non-empty string that contains
175178
// new mapper device name (e.g. /dev/mapper/name)
176-
func handleMapperDeviceUevent(ev *uevent.Uevent) error {
177-
devName := ev.Vars["DEVNAME"]
179+
func handleMapperDeviceUevent(ev netlink.UEvent) error {
180+
devName := ev.Env["DEVNAME"]
178181

179-
major, err := strconv.Atoi(ev.Vars["MAJOR"])
182+
major, err := strconv.Atoi(ev.Env["MAJOR"])
180183
if err != nil {
181184
return fmt.Errorf("udev['MAJOR']: %v", err)
182185
}
183-
minor, err := strconv.Atoi(ev.Vars["MINOR"])
186+
minor, err := strconv.Atoi(ev.Env["MINOR"])
184187
if err != nil {
185188
return fmt.Errorf("udev['MAJOR']: %v", err)
186189
}

0 commit comments

Comments
 (0)