Skip to content

Commit 40e2722

Browse files
authored
Merge pull request #249 from lucab/ups/safer-dbus
dbus: make SetSubStateSubscriber safer
2 parents 90ece6e + 9750bea commit 40e2722

File tree

1 file changed

+49
-9
lines changed

1 file changed

+49
-9
lines changed

dbus/subscription.go

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package dbus
1616

1717
import (
1818
"errors"
19+
"log"
1920
"time"
2021

2122
"github.com/godbus/dbus"
@@ -176,6 +177,16 @@ type SubStateUpdate struct {
176177
// is full, it attempts to write an error to errCh; if errCh is full, the error
177178
// passes silently.
178179
func (c *Conn) SetSubStateSubscriber(updateCh chan<- *SubStateUpdate, errCh chan<- error) {
180+
if c == nil {
181+
msg := "nil receiver"
182+
select {
183+
case errCh <- errors.New(msg):
184+
default:
185+
log.Printf("full error channel while reporting: %s\n", msg)
186+
}
187+
return
188+
}
189+
179190
c.subStateSubscriber.Lock()
180191
defer c.subStateSubscriber.Unlock()
181192
c.subStateSubscriber.updateCh = updateCh
@@ -190,7 +201,9 @@ func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) {
190201
return
191202
}
192203

193-
if c.shouldIgnore(unitPath) {
204+
isIgnored := c.shouldIgnore(unitPath)
205+
defer c.cleanIgnore()
206+
if isIgnored {
194207
return
195208
}
196209

@@ -199,23 +212,45 @@ func (c *Conn) sendSubStateUpdate(unitPath dbus.ObjectPath) {
199212
select {
200213
case c.subStateSubscriber.errCh <- err:
201214
default:
215+
log.Printf("full error channel while reporting: %s\n", err)
202216
}
217+
return
203218
}
219+
defer c.updateIgnore(unitPath, info)
204220

205-
name := info["Id"].(string)
206-
substate := info["SubState"].(string)
221+
name, ok := info["Id"].(string)
222+
if !ok {
223+
msg := "failed to cast info.Id"
224+
select {
225+
case c.subStateSubscriber.errCh <- errors.New(msg):
226+
default:
227+
log.Printf("full error channel while reporting: %s\n", err)
228+
}
229+
return
230+
}
231+
substate, ok := info["SubState"].(string)
232+
if !ok {
233+
msg := "failed to cast info.SubState"
234+
select {
235+
case c.subStateSubscriber.errCh <- errors.New(msg):
236+
default:
237+
log.Printf("full error channel while reporting: %s\n", msg)
238+
}
239+
return
240+
}
207241

208242
update := &SubStateUpdate{name, substate}
209243
select {
210244
case c.subStateSubscriber.updateCh <- update:
211245
default:
246+
msg := "update channel is full"
212247
select {
213-
case c.subStateSubscriber.errCh <- errors.New("update channel full!"):
248+
case c.subStateSubscriber.errCh <- errors.New(msg):
214249
default:
250+
log.Printf("full error channel while reporting: %s\n", msg)
215251
}
252+
return
216253
}
217-
218-
c.updateIgnore(unitPath, info)
219254
}
220255

221256
// The ignore functions work around a wart in the systemd dbus interface.
@@ -238,10 +273,13 @@ func (c *Conn) shouldIgnore(path dbus.ObjectPath) bool {
238273
}
239274

240275
func (c *Conn) updateIgnore(path dbus.ObjectPath, info map[string]interface{}) {
241-
c.cleanIgnore()
276+
loadState, ok := info["LoadState"].(string)
277+
if !ok {
278+
return
279+
}
242280

243281
// unit is unloaded - it will trigger bad systemd dbus behavior
244-
if info["LoadState"].(string) == "not-found" {
282+
if loadState == "not-found" {
245283
c.subStateSubscriber.ignore[path] = time.Now().UnixNano() + ignoreInterval
246284
}
247285
}
@@ -294,9 +332,11 @@ func (c *Conn) sendPropertiesUpdate(unitPath dbus.ObjectPath, changedProps map[s
294332
select {
295333
case c.propertiesSubscriber.updateCh <- update:
296334
default:
335+
msg := "update channel is full"
297336
select {
298-
case c.propertiesSubscriber.errCh <- errors.New("update channel is full"):
337+
case c.propertiesSubscriber.errCh <- errors.New(msg):
299338
default:
339+
log.Printf("full error channel while reporting: %s\n", msg)
300340
}
301341
return
302342
}

0 commit comments

Comments
 (0)