summaryrefslogtreecommitdiffstats
path: root/document
diff options
context:
space:
mode:
authorTor Brede Vekterli <vekterli@yahooinc.com>2022-03-03 14:35:25 +0000
committerTor Brede Vekterli <vekterli@yahooinc.com>2022-03-03 14:55:02 +0000
commitf455b53f3733ca0848d04e3587fd3d70c35ebf54 (patch)
treecce7adb8a022e215b1140419cda000cc1802970e /document
parent6f78fdc9750ad3ac03b14166b6838c628487458c (diff)
Explicitly precompute GlobalId for reference values to avoid lazy init race
This is a workaround for `DocumentId::getGlobalId()`'s lazy GID computation currently not being thread safe in a `const` context. The following race was previously possible: * Attribute writer thread calls `DocumentId::getGlobalId` when applying the reference value update to a reference attribute. Writes GID and flag. * Shared executor thread calls `DocumentId::operator=` with the same ID instance as the rhs argument when applying the reference value update to the doc store. Causes a read race with the above write.
Diffstat (limited to 'document')
-rw-r--r--document/src/vespa/document/base/documentid.cpp3
-rw-r--r--document/src/vespa/document/fieldvalue/referencefieldvalue.cpp2
2 files changed, 4 insertions, 1 deletions
diff --git a/document/src/vespa/document/base/documentid.cpp b/document/src/vespa/document/base/documentid.cpp
index f3045cd0758..cb5320db538 100644
--- a/document/src/vespa/document/base/documentid.cpp
+++ b/document/src/vespa/document/base/documentid.cpp
@@ -59,8 +59,9 @@ DocumentId::calculateGlobalId() const
IdString::LocationType location(_id.getLocation());
memcpy(key, &location, 4);
- _globalId.first = true;
+ // FIXME this lazy init mechanic does not satisfy const thread safety
_globalId.second.set(key);
+ _globalId.first = true;
}
std::ostream &
diff --git a/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp b/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp
index 83890c1acfc..328e5b67151 100644
--- a/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp
+++ b/document/src/vespa/document/fieldvalue/referencefieldvalue.cpp
@@ -75,6 +75,8 @@ void ReferenceFieldValue::setDeserializedDocumentId(const DocumentId& id) {
assert(_dataType != nullptr);
requireIdOfMatchingType(id, _dataType->getTargetType());
_documentId = id;
+ // Pre-cache GID to ensure it's not attempted lazily initialized later in a racing manner.
+ (void) _documentId.getGlobalId();
_altered = false;
}