canonical / pebble

Pebble is a lightweight Linux service manager with layered configuration and an HTTP API.
https://canonical-pebble.readthedocs-hosted.com/
GNU General Public License v3.0
146 stars 54 forks source link

fix(servstate): reduce scope of holding ServiceManager.planLock #355

Closed benhoyt closed 7 months ago

benhoyt commented 7 months ago

In most cases we're just reading from m.plan fields (Services, DefaultServiceNames, and so on), so we can use m.Plan(), which holds the plan lock only for the duration of fetch m.plan -- this is safe, because we never mutate what's inside m.plan, we only replace it (in updatePlan).

This also means that in functions like Services() we're only holding either the plan lock or the services lock at once, not both -- avoiding the 3-way deadlock described in #314.

For the cases we are updating the plan (AppendLayer, CombineLayer, SetServiceArgs), we still need acquirePlan.

In ServiceManager.ServiceLogs, we don't need to acquire the plan lock at all (m.plan isn't used).

Fixes #314.