From 085c827caf1e57c9d213ef74c2834679df06b1d9 Mon Sep 17 00:00:00 2001 From: Jonas Licht Date: Fri, 13 Oct 2023 15:59:27 +0200 Subject: [PATCH 1/2] dbus/methods: observe context for Cancellation to remove job listener Oberserve the given context from the function e.g. StartUnitContext, which are using the internal function startJob. If this context is done remove the job Listener if existing. Fixes #428 --- dbus/methods.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/dbus/methods.go b/dbus/methods.go index 074148cb..10bafa9c 100644 --- a/dbus/methods.go +++ b/dbus/methods.go @@ -67,12 +67,27 @@ func (c *Conn) startJob(ctx context.Context, ch chan<- string, job string, args c.jobListener.jobs[p] = ch } + go c.observeContextCancellation(ctx, p) + // ignore error since 0 is fine if conversion fails jobID, _ := strconv.Atoi(path.Base(string(p))) return jobID, nil } +func (c *Conn) observeContextCancellation(ctx context.Context, jobId dbus.ObjectPath) { + <-ctx.Done() + + // remove job listener if one exists + c.jobListener.Lock() + defer c.jobListener.Unlock() + + _, ok := c.jobListener.jobs[jobId] + if ok { + delete(c.jobListener.jobs, jobId) + } +} + // Deprecated: use StartUnitContext instead. func (c *Conn) StartUnit(name string, mode string, ch chan<- string) (int, error) { return c.StartUnitContext(context.Background(), name, mode, ch) From 838f5a9ff3fab1dcca9227abce9fdef10d95c97b Mon Sep 17 00:00:00 2001 From: Jonas Licht Date: Fri, 13 Oct 2023 16:06:45 +0200 Subject: [PATCH 2/2] dbus/methods: don't write blocking to jobListener channel When handling the jobComplete signal, only try to write to the channel and do not block on the channel write. If nothing reads from this channel, the function blocks forever and makes it impossible to start new jobs. Fixes #429 --- dbus/methods.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/dbus/methods.go b/dbus/methods.go index 10bafa9c..c00a49b7 100644 --- a/dbus/methods.go +++ b/dbus/methods.go @@ -45,7 +45,10 @@ func (c *Conn) jobComplete(signal *dbus.Signal) { c.jobListener.Lock() out, ok := c.jobListener.jobs[job] if ok { - out <- result + select { + case out <- result: + default: + } delete(c.jobListener.jobs, job) } c.jobListener.Unlock()