From cea119449e4ba0933ce22bc9f54a9cb21217d758 Mon Sep 17 00:00:00 2001 From: Marty Schoch Date: Mon, 7 Aug 2017 15:11:35 -0400 Subject: [PATCH] fix data race in doc id search the implementation of the doc id search requires that the list of ids be sorted. however, when doing a multisearch across many indexes at once, the list of doc ids in the query is shared. deeper in the implementation, the search of each shard attempts to sort this list, resulting in a data race. this is one example of a potentially larger problem, however it has been decided to fix this data race, even though larger issues of data owernship may remain unresolved. this fix makes a copy of the list of doc ids, just prior to sorting the list. subsequently, all use of the list is on the copy that was made, not the original. fixes #518 --- index/upsidedown/reader.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/index/upsidedown/reader.go b/index/upsidedown/reader.go index 76032bf5..1f40c02d 100644 --- a/index/upsidedown/reader.go +++ b/index/upsidedown/reader.go @@ -190,15 +190,18 @@ func newUpsideDownCouchDocIDReader(indexReader *IndexReader) (*UpsideDownCouchDo } func newUpsideDownCouchDocIDReaderOnly(indexReader *IndexReader, ids []string) (*UpsideDownCouchDocIDReader, error) { + // we don't actually own the list of ids, so if before we sort we must copy + idsCopy := make([]string, len(ids)) + copy(idsCopy, ids) // ensure ids are sorted - sort.Strings(ids) + sort.Strings(idsCopy) startBytes := []byte{0x0} - if len(ids) > 0 { - startBytes = []byte(ids[0]) + if len(idsCopy) > 0 { + startBytes = []byte(idsCopy[0]) } endBytes := []byte{0xff} - if len(ids) > 0 { - endBytes = incrementBytes([]byte(ids[len(ids)-1])) + if len(idsCopy) > 0 { + endBytes = incrementBytes([]byte(idsCopy[len(idsCopy)-1])) } bisr := NewBackIndexRow(startBytes, nil, nil) bier := NewBackIndexRow(endBytes, nil, nil) @@ -207,7 +210,7 @@ func newUpsideDownCouchDocIDReaderOnly(indexReader *IndexReader, ids []string) ( return &UpsideDownCouchDocIDReader{ indexReader: indexReader, iterator: it, - only: ids, + only: idsCopy, onlyMode: true, }, nil }