it fixes race with access to containerMutexes
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
(cherry picked from commit a7851e2556edb3e5333b6fe53160755fb5b7d616)
| ... | ... |
@@ -4,35 +4,23 @@ import ( |
| 4 | 4 |
"fmt" |
| 5 | 5 |
"sync" |
| 6 | 6 |
|
| 7 |
- "github.com/Sirupsen/logrus" |
|
| 7 |
+ "github.com/docker/docker/pkg/locker" |
|
| 8 | 8 |
) |
| 9 | 9 |
|
| 10 | 10 |
// clientCommon contains the platform agnostic fields used in the client structure |
| 11 | 11 |
type clientCommon struct {
|
| 12 |
- backend Backend |
|
| 13 |
- containers map[string]*container |
|
| 14 |
- containerMutexes map[string]*sync.Mutex // lock by container ID |
|
| 15 |
- mapMutex sync.RWMutex // protects read/write oprations from containers map |
|
| 16 |
- sync.Mutex // lock for containerMutexes map access |
|
| 12 |
+ backend Backend |
|
| 13 |
+ containers map[string]*container |
|
| 14 |
+ locker *locker.Locker |
|
| 15 |
+ mapMutex sync.RWMutex // protects read/write oprations from containers map |
|
| 17 | 16 |
} |
| 18 | 17 |
|
| 19 | 18 |
func (clnt *client) lock(containerID string) {
|
| 20 |
- clnt.Lock() |
|
| 21 |
- if _, ok := clnt.containerMutexes[containerID]; !ok {
|
|
| 22 |
- clnt.containerMutexes[containerID] = &sync.Mutex{}
|
|
| 23 |
- } |
|
| 24 |
- clnt.Unlock() |
|
| 25 |
- clnt.containerMutexes[containerID].Lock() |
|
| 19 |
+ clnt.locker.Lock(containerID) |
|
| 26 | 20 |
} |
| 27 | 21 |
|
| 28 | 22 |
func (clnt *client) unlock(containerID string) {
|
| 29 |
- clnt.Lock() |
|
| 30 |
- if l, ok := clnt.containerMutexes[containerID]; ok {
|
|
| 31 |
- l.Unlock() |
|
| 32 |
- } else {
|
|
| 33 |
- logrus.Warnf("unlock of non-existing mutex: %s", containerID)
|
|
| 34 |
- } |
|
| 35 |
- clnt.Unlock() |
|
| 23 |
+ clnt.locker.Unlock(containerID) |
|
| 36 | 24 |
} |
| 37 | 25 |
|
| 38 | 26 |
// must hold a lock for cont.containerID |
| ... | ... |
@@ -16,6 +16,7 @@ import ( |
| 16 | 16 |
|
| 17 | 17 |
"github.com/Sirupsen/logrus" |
| 18 | 18 |
containerd "github.com/docker/containerd/api/grpc/types" |
| 19 |
+ "github.com/docker/docker/pkg/locker" |
|
| 19 | 20 |
sysinfo "github.com/docker/docker/pkg/system" |
| 20 | 21 |
"github.com/docker/docker/utils" |
| 21 | 22 |
"golang.org/x/net/context" |
| ... | ... |
@@ -169,9 +170,9 @@ func (r *remote) Cleanup() {
|
| 169 | 169 |
func (r *remote) Client(b Backend) (Client, error) {
|
| 170 | 170 |
c := &client{
|
| 171 | 171 |
clientCommon: clientCommon{
|
| 172 |
- backend: b, |
|
| 173 |
- containerMutexes: make(map[string]*sync.Mutex), |
|
| 174 |
- containers: make(map[string]*container), |
|
| 172 |
+ backend: b, |
|
| 173 |
+ containers: make(map[string]*container), |
|
| 174 |
+ locker: locker.New(), |
|
| 175 | 175 |
}, |
| 176 | 176 |
remote: r, |
| 177 | 177 |
exitNotifiers: make(map[string]*exitNotifier), |
| ... | ... |
@@ -1,6 +1,6 @@ |
| 1 | 1 |
package libcontainerd |
| 2 | 2 |
|
| 3 |
-import "sync" |
|
| 3 |
+import "github.com/docker/docker/pkg/locker" |
|
| 4 | 4 |
|
| 5 | 5 |
type remote struct {
|
| 6 | 6 |
} |
| ... | ... |
@@ -8,9 +8,9 @@ type remote struct {
|
| 8 | 8 |
func (r *remote) Client(b Backend) (Client, error) {
|
| 9 | 9 |
c := &client{
|
| 10 | 10 |
clientCommon: clientCommon{
|
| 11 |
- backend: b, |
|
| 12 |
- containerMutexes: make(map[string]*sync.Mutex), |
|
| 13 |
- containers: make(map[string]*container), |
|
| 11 |
+ backend: b, |
|
| 12 |
+ containers: make(map[string]*container), |
|
| 13 |
+ locker: locker.New(), |
|
| 14 | 14 |
}, |
| 15 | 15 |
} |
| 16 | 16 |
return c, nil |