Browse code

Add RWMutex lock into TruncIndex to fix race condition when inserting values

The idx.index array is overwritten when a new value is inserted to the index.
When two containers are created concurrently, their ids are inserted to the
index and one can overwrite the other leaving one of ids missing from the
index. Adding a RWMutex lock around read/write operations fixes this.

Docker-DCO-1.1-Signed-off-by: James Allen <jamesallen0108@gmail.com> (github: jpallen)

James Allen authored on 2014/01/16 02:29:46
Showing 1 changed files
... ...
@@ -418,6 +418,7 @@ func GetTotalUsedFds() int {
418 418
 // TruncIndex allows the retrieval of string identifiers by any of their unique prefixes.
419 419
 // This is used to retrieve image and container IDs by more convenient shorthand prefixes.
420 420
 type TruncIndex struct {
421
+	sync.RWMutex
421 422
 	index *suffixarray.Index
422 423
 	ids   map[string]bool
423 424
 	bytes []byte
... ...
@@ -432,6 +433,8 @@ func NewTruncIndex() *TruncIndex {
432 432
 }
433 433
 
434 434
 func (idx *TruncIndex) Add(id string) error {
435
+	idx.Lock()
436
+	defer idx.Unlock()
435 437
 	if strings.Contains(id, " ") {
436 438
 		return fmt.Errorf("Illegal character: ' '")
437 439
 	}
... ...
@@ -445,6 +448,8 @@ func (idx *TruncIndex) Add(id string) error {
445 445
 }
446 446
 
447 447
 func (idx *TruncIndex) Delete(id string) error {
448
+	idx.Lock()
449
+	defer idx.Unlock()
448 450
 	if _, exists := idx.ids[id]; !exists {
449 451
 		return fmt.Errorf("No such id: %s", id)
450 452
 	}
... ...
@@ -470,6 +475,8 @@ func (idx *TruncIndex) lookup(s string) (int, int, error) {
470 470
 }
471 471
 
472 472
 func (idx *TruncIndex) Get(s string) (string, error) {
473
+	idx.RLock()
474
+	defer idx.RUnlock()
473 475
 	before, after, err := idx.lookup(s)
474 476
 	//log.Printf("Get(%s) bytes=|%s| before=|%d| after=|%d|\n", s, idx.bytes, before, after)
475 477
 	if err != nil {