Skip to content

Commit de87d4b

Browse files
committed
CXX-382 Backport server r2.7.8..r2.7.9 fixes to legacy branch
1 parent dae3e43 commit de87d4b

28 files changed

+232
-448
lines changed

SConstruct

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,7 +1297,8 @@ def doConfigure(myenv):
12971297

12981298
sanitizer_list = get_option('sanitize').split(',')
12991299

1300-
using_asan = 'address' in sanitizer_list or 'leak' in sanitizer_list
1300+
using_lsan = 'leak' in sanitizer_list
1301+
using_asan = 'address' in sanitizer_list or using_lsan
13011302

13021303
# If the user asked for leak sanitizer turn on the detect_leaks
13031304
# ASAN_OPTION. If they asked for address sanitizer as well, drop
@@ -1307,8 +1308,10 @@ def doConfigure(myenv):
13071308
# --sanitize=address,leak: -fsanitize=address, detect_leaks=1
13081309
# --sanitize=address: -fsanitize=address
13091310
#
1310-
if 'leak' in sanitizer_list:
1311-
myenv['ENV']['ASAN_OPTIONS'] = "detect_leaks=1"
1311+
if using_lsan:
1312+
if using_asan:
1313+
myenv['ENV']['ASAN_OPTIONS'] = "detect_leaks=1"
1314+
myenv['ENV']['LSAN_OPTIONS'] = "suppressions=%s" % myenv.File("#etc/lsan.suppressions").abspath
13121315
if 'address' in sanitizer_list:
13131316
sanitizer_list.remove('leak')
13141317

@@ -1321,12 +1324,34 @@ def doConfigure(myenv):
13211324
print( 'Failed to enable sanitizers with flag: ' + sanitizer_option )
13221325
Exit(1)
13231326

1327+
blackfiles_map = {
1328+
"address" : myenv.File("#etc/asan.blacklist"),
1329+
"leak" : myenv.File("#etc/asan.blacklist"),
1330+
"thread" : myenv.File("#etc/tsan.blacklist"),
1331+
"undefined" : myenv.File("#etc/ubsan.blacklist"),
1332+
}
1333+
1334+
blackfiles = set([v for (k, v) in blackfiles_map.iteritems() if k in sanitizer_list])
1335+
blacklist_options=["-fsanitize-blacklist=%s" % blackfile for blackfile in blackfiles]
1336+
1337+
for blacklist_option in blacklist_options:
1338+
if AddToCCFLAGSIfSupported(myenv, blacklist_option):
1339+
myenv.Append(LINKFLAGS=[blacklist_option])
1340+
13241341
llvm_symbolizer = get_option('llvm-symbolizer')
1325-
if not os.path.isabs(llvm_symbolizer):
1342+
if os.path.isabs(llvm_symbolizer):
1343+
if not myenv.File(llvm_symbolizer).exists():
1344+
print("WARNING: Specified symbolizer '%s' not found" % llvm_symbolizer)
1345+
llvm_symbolizer = None
1346+
else:
13261347
llvm_symbolizer = myenv.WhereIs(llvm_symbolizer)
1348+
13271349
if llvm_symbolizer:
1328-
if using_asan:
1329-
myenv['ENV']['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
1350+
myenv['ENV']['ASAN_SYMBOLIZER_PATH'] = llvm_symbolizer
1351+
myenv['ENV']['LSAN_SYMBOLIZER_PATH'] = llvm_symbolizer
1352+
elif using_lsan:
1353+
print("Using the leak sanitizer requires a valid symbolizer")
1354+
Exit(1)
13301355

13311356
# When using msvc, check for VS 2013 Update 2+ so we can use new compiler flags
13321357
if using_msvc():

etc/asan.blacklist

Whitespace-only changes.

etc/lsan.suppressions

Whitespace-only changes.

etc/tsan.blacklist

Whitespace-only changes.

etc/ubsan.blacklist

Whitespace-only changes.

src/SConscript.client

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ clientHeaders = [
312312
'mongo/util/net/message_port.h',
313313
'mongo/util/net/operation.h',
314314
'mongo/util/net/sock.h',
315+
'mongo/util/shared_buffer.h',
315316
'mongo/util/time_support.h',
316317
'mongo/version.h',
317318
]

src/mongo/base/error_codes.err

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ error_code("RoleDataInconsistent", 80)
8383
error_code("NoWhereParseContext", 81)
8484
error_code("NoProgressMade", 82)
8585
error_code("RemoteResultsUnavailable", 83)
86-
error_code("UniqueIndexViolation", 84)
86+
error_code("DuplicateKeyValue", 84)
8787
error_code("IndexOptionsConflict", 85 )
8888
error_code("IndexKeySpecsConflict", 86 )
8989
error_code("CannotSplit", 87)
@@ -111,7 +111,7 @@ error_code("InconsistentReplicaSetNames", 108)
111111
error_code("ConfigurationInProgress", 109)
112112
error_code("CannotInitializeNodeWithData", 110)
113113
error_code("NotExactValueField", 111)
114-
error_code("DeadLock", 112)
114+
error_code("WriteConflict", 112)
115115

116116
# Non-sequential error codes (for compatibility only)
117117
error_code("NotMaster", 10107) #this comes from assert_util.h

src/mongo/bson/bsonobj.h

Lines changed: 15 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "mongo/bson/util/builder.h"
3232
#include "mongo/client/export_macros.h"
3333
#include "mongo/platform/atomic_word.h"
34+
#include "mongo/util/shared_buffer.h"
3435

3536
namespace mongo {
3637

@@ -94,11 +95,16 @@ namespace mongo {
9495
init(bsonData);
9596
}
9697

98+
explicit BSONObj(SharedBuffer ownedBuffer)
99+
: _objdata(ownedBuffer.get() ? ownedBuffer.get() : BSONObj().objdata())
100+
, _ownedBuffer(ownedBuffer.moveFrom()) {
101+
}
102+
97103
#if __cplusplus >= 201103L
98104
/** Move construct a BSONObj */
99105
BSONObj(BSONObj&& other)
100106
: _objdata(std::move(other._objdata))
101-
, _holder(std::move(other._holder)) {
107+
, _ownedBuffer(std::move(other._ownedBuffer)) {
102108
other._objdata = BSONObj()._objdata; // To return to an empty state.
103109
}
104110

@@ -121,7 +127,7 @@ namespace mongo {
121127
void swap(BSONObj& other) {
122128
using std::swap;
123129
swap(_objdata, other._objdata);
124-
swap(_holder, other._holder);
130+
swap(_ownedBuffer, other._ownedBuffer);
125131
}
126132

127133
/**
@@ -152,7 +158,7 @@ namespace mongo {
152158
153159
@return true if this is in owned mode
154160
*/
155-
bool isOwned() const { return _holder.get() != 0; }
161+
bool isOwned() const { return _ownedBuffer.get() != 0; }
156162

157163
/** assure the data buffer is under the control of this BSONObj and not a remote buffer
158164
@see isOwned()
@@ -510,59 +516,20 @@ namespace mongo {
510516

511517
template<typename T> bool coerceVector( std::vector<T>* out ) const;
512518

513-
class Holder {
514-
public:
515-
explicit Holder(AtomicUInt32::WordType initial = AtomicUInt32::WordType())
516-
: _refCount(initial) {}
517-
518-
// these are called automatically by boost::intrusive_ptr
519-
friend void intrusive_ptr_add_ref(Holder* h) {
520-
h->_refCount.fetchAndAdd(1);
521-
}
522-
523-
friend void intrusive_ptr_release(Holder* h) {
524-
if (h->_refCount.subtractAndFetch(1) == 0) {
525-
// We placement new'ed a Holder in BSONObj::takeOwnership below,
526-
// so we must destroy the object here.
527-
h->~Holder();
528-
free(h);
529-
}
530-
}
531-
532-
char* data() {
533-
return reinterpret_cast<char *>(this + 1);
534-
}
535-
536-
const char* data() const {
537-
return reinterpret_cast<const char *>(this + 1);
538-
}
539-
540-
private:
541-
AtomicUInt32 _refCount;
542-
};
519+
typedef SharedBuffer::Holder Holder;
543520

544521
/** Given a pointer to a region of un-owned memory containing BSON data, prefixed by
545522
* sufficient space for a BSONObj::Holder object, return a BSONObj that owns the
546523
* memory.
524+
*
525+
* This class will call free(holderPrefixedData), so it must have been allocated in a way
526+
* that makes that valid.
547527
*/
548528
static BSONObj takeOwnership(char* holderPrefixedData) {
549-
// Initialize the refcount to 1 so we don't need to increment it in the constructor
550-
// (see private BSONObj(Holder*) constructor below).
551-
//
552-
// TODO: Should dassert alignment of holderPrefixedData
553-
// here if possible.
554-
return BSONObj(new(holderPrefixedData) BSONObj::Holder(1U));
529+
return BSONObj(SharedBuffer::takeOwnership(holderPrefixedData));
555530
}
556531

557532
private:
558-
/** Construct a new BSONObj using the given Holder object */
559-
explicit BSONObj(Holder* holder)
560-
: _holder(holder, false) {
561-
// NOTE: The 'false' is because we have already initialized the Holder with a
562-
// refcount of '1' in takeOwnership above.
563-
init(holder->data());
564-
}
565-
566533
void _assertInvalid() const;
567534

568535
void init(const char *data) {
@@ -580,7 +547,7 @@ namespace mongo {
580547
Status _okForStorage(bool root, bool deep) const;
581548

582549
const char* _objdata;
583-
boost::intrusive_ptr< Holder > _holder;
550+
SharedBuffer _ownedBuffer;
584551
};
585552

586553
MONGO_CLIENT_API std::ostream& MONGO_CLIENT_FUNC operator<<( std::ostream &s, const BSONObj &o );

src/mongo/bson/util/bson_extract.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ namespace mongo {
105105
return Status::OK();
106106
}
107107

108+
Status bsonExtractOIDFieldWithDefault(const BSONObj& object,
109+
const StringData& fieldName,
110+
const OID& defaultValue,
111+
OID* out) {
112+
Status status = bsonExtractOIDField(object, fieldName, out);
113+
if (status == ErrorCodes::NoSuchKey) {
114+
*out = defaultValue;
115+
}
116+
else if (!status.isOK()) {
117+
return status;
118+
}
119+
return Status::OK();
120+
}
121+
108122
Status bsonExtractStringFieldWithDefault(const BSONObj& object,
109123
const StringData& fieldName,
110124
const StringData& defaultValue,

src/mongo/bson/util/bson_extract.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,4 +159,17 @@ namespace mongo {
159159
const StringData& defaultValue,
160160
std::string* out);
161161

162+
/**
163+
* Finds an OID-typed element named "fieldName" in "object" and stores its value in *out.
164+
*
165+
* Returns Status::OK() and sets *out to the found element's OID value on success. If no field
166+
* named "fieldName" is present, *out is set to "defaultValue" and Status::OK() is returned.
167+
* Returns ErrorCodes::TypeMismatch if the type of the matching element is not OID. For return
168+
* values other than Status::OK(), the resulting value of *out is undefined.
169+
*/
170+
Status bsonExtractOIDFieldWithDefault(const BSONObj& object,
171+
const StringData& fieldName,
172+
const OID& defaultValue,
173+
OID* out);
174+
162175
} // namespace mongo

0 commit comments

Comments
 (0)