mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
cluster: Avoid recursive RLock
GetTasks can call GetService and GetNode with the read lock held. These methods try to aquire the read side of the same lock. According to the sync package documentation, this is not safe: > If a goroutine holds a RWMutex for reading, it must not expect this or > any other goroutine to be able to also take the read lock until the > first read lock is released. In particular, this prohibits recursive > read locking. This is to ensure that the lock eventually becomes > available; a blocked Lock call excludes new readers from acquiring the > lock. Fix GetTasks to use the lower-level getService and getNode methods instead. Also, use lockedManagerAction to simplify GetTasks. Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>
This commit is contained in:
parent
4ac4c8ef4b
commit
bd4f66c8f1
1 changed files with 36 additions and 43 deletions
|
@ -11,19 +11,14 @@ import (
|
|||
|
||||
// GetTasks returns a list of tasks matching the filter options.
|
||||
func (c *Cluster) GetTasks(options apitypes.TaskListOptions) ([]types.Task, error) {
|
||||
c.mu.RLock()
|
||||
defer c.mu.RUnlock()
|
||||
|
||||
state := c.currentNodeState()
|
||||
if !state.IsActiveManager() {
|
||||
return nil, c.errNoManager(state)
|
||||
}
|
||||
var r *swarmapi.ListTasksResponse
|
||||
|
||||
if err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
|
||||
filterTransform := func(filter filters.Args) error {
|
||||
if filter.Include("service") {
|
||||
serviceFilters := filter.Get("service")
|
||||
for _, serviceFilter := range serviceFilters {
|
||||
service, err := c.GetService(serviceFilter, false)
|
||||
service, err := getService(ctx, state.controlClient, serviceFilter, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -34,7 +29,7 @@ func (c *Cluster) GetTasks(options apitypes.TaskListOptions) ([]types.Task, erro
|
|||
if filter.Include("node") {
|
||||
nodeFilters := filter.Get("node")
|
||||
for _, nodeFilter := range nodeFilters {
|
||||
node, err := c.GetNode(nodeFilter)
|
||||
node, err := getNode(ctx, state.controlClient, nodeFilter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -52,16 +47,14 @@ func (c *Cluster) GetTasks(options apitypes.TaskListOptions) ([]types.Task, erro
|
|||
|
||||
filters, err := newListTasksFilters(options.Filters, filterTransform)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
ctx, cancel := c.getRequestContext()
|
||||
defer cancel()
|
||||
|
||||
r, err := state.controlClient.ListTasks(
|
||||
r, err = state.controlClient.ListTasks(
|
||||
ctx,
|
||||
&swarmapi.ListTasksRequest{Filters: filters})
|
||||
if err != nil {
|
||||
return err
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue