[SERVER-74641] EPrimBinary fails to compile with "Can't remove label that has outstanding fixups. labelId:1" Created: 06/Mar/23  Updated: 29/Oct/23  Resolved: 21/Mar/23

Status: Closed
Project: Core Server
Component/s: None
Affects Version/s: None
Fix Version/s: 7.0.0-rc0

Type: Task Priority: Major - P3
Reporter: Anna Wawrzyniak Assignee: Anna Wawrzyniak
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Tested
tested by SERVER-74785 [CQF] Enable find().sort() to work co... Backlog
Backwards Compatibility: Fully Compatible
Sprint: QE 2023-03-20, QE 2023-04-03
Participants:

 Description   

This issue seems to be caused by ambigous interaction between LabelScope destructor and "return code" statement.

Explicitly calling removeLabel appears to fix the issue.

https://github.com/10gen/mongo/blob/anna.wawrzyniak/autoparam_limit/src/mongo/db/exec/sbe/expressions/expression.cpp#L292 
 
https://logkeeper2.build.10gen.cc/build/3dcbc442b4b0ea4f4dcea0c194c5995d/test/1749dd4199187f62427454aa887bbe76?raw=1

Failure:

[j0] {"t":{"$date":"2023-03-05T00:24:21.465+00:00"},"s":"E",  "c":"ASSERT",   "id":4457000, "ctx":"conn41","msg":"Tripwire assertion","attr":{"error":{"code":7134601,"codeName":"Location7134601","errmsg":"Can't remove label that has outstanding fixups. labelId:1"},"location":"{fileName:\"src/mongo/db/exec/sbe/vm/vm.cpp\", line:279, functionName:\"removeLabel\"}"}}
[j0] {"t":{"$date":"2023-03-05T00:24:21.698+00:00"},"s":"I",  "c":"CONTROL",  "id":31380,   "ctx":"conn41","msg":"BACKTRACE","attr":{"bt":{"backtrace":[{"a":"7F12EC40FA28","b":"7F12EC1E2000","o":"22DA28","s":"_ZN5mongo18stack_trace_detail12_GLOBAL__N_117getStackTraceImplERKNS1_7OptionsE.constprop.0","C":"mongo::stack_trace_detail::(anonymous namespace)::getStackTraceImpl(mongo::stack_trace_detail::(anonymous namespace)::Options const&) [clone .constprop.0]","s+":"228"},{"a":"7F12EC4116A8","b":"7F12EC1E2000","o":"22F6A8","s":"_ZN5mongo15printStackTraceEv","C":"mongo::printStackTrace()","s+":"38"},{"a":"7F12EC400013","b":"7F12EC1E2000","o":"21E013","s":"_ZN5mongo13tassertFailedERKNS_6StatusENS_14SourceLocationE","C":"mongo::tassertFailed(mongo::Status const&, mongo::SourceLocation)","s+":"123"},{"a":"7F12E5B9A0B8","b":"7F12E5AFF000","o":"9B0B8","s":"_ZN5mongo3sbe2vm12CodeFragment11removeLabelEl.cold","C":"mongo::sbe::vm::CodeFragment::removeLabel(long) [clone .cold]","s+":"60"},{"a":"7F12E5B7D6F0","b":"7F12E5AFF000","o":"7E6F0","s":"_ZN5mongo3sbe2vm10LabelScopeD2Ev","C":"mongo::sbe::vm::LabelScope::~LabelScope()","s+":"10"},{"a":"7F12E5B51BFC","b":"7F12E5AFF000","o":"52BFC","s":"_ZNK5mongo3sbe11EPrimBinary13compileDirectERNS0_10CompileCtxE.cold","C":"mongo::sbe::EPrimBinary::compileDirect(mongo::sbe::CompileCtx&) const [clone .cold]","s+":"108"},{"a":"7F12E5B46ED2","b":"7F12E5AFF000","o":"47ED2","s":"_ZNK5mongo3sbe3EIf13compileDirectERNS0_10CompileCtxE","C":"mongo::sbe::EIf::compileDirect(mongo::sbe::CompileCtx&) const","s+":"42"},{"a":"7F12E5B471DF","b":"7F12E5AFF000","o":"481DF","s":"_ZNK5mongo3sbe10ELocalBind13compileDirectERNS0_10CompileCtxE","C":"mongo::sbe::ELocalBind::compileDirect(mongo::sbe::CompileCtx&) const","s+":"DF"},{"a":"7F12E5B499F6","b":"7F12E5AFF000","o":"4A9F6","s":"_ZNK5mongo3sbe11EExpression7compileERNS0_10CompileCtxE","C":"mongo::sbe::EExpression::compile(mongo::sbe::CompileCtx&) const","s+":"36"},{"a":"7F12E5D631EC","b":"7F12E5C3A000","o":"1291EC","s":"_ZN5mongo3sbe12ProjectStage7prepareERNS0_10CompileCtxE","C":"mongo::sbe::ProjectStage::prepare(mongo::sbe::CompileCtx&)","s+":"BC"},{"a":"7F12E70E7C60","b":"7F12E6D1F000","o":"3C8C60","s":"_ZN5mongo34getSBEExecutorViaCascadesOptimizerEPNS_16OperationContextEN5boost13intrusive_ptrINS_17ExpressionContextEEERKNS_15NamespaceStringERKNS_13CollectionPtrENS_9optimizer10QueryHintsERKNS2_8optionalINS_7BSONObjEEEPKNS_8PipelineEPKNS_14CanonicalQueryE","C":"mongo::getSBEExecutorViaCascadesOptimizer(mongo::OperationContext*, boost::intrusive_ptr<mongo::ExpressionContext>, mongo::NamespaceString const&, mongo::CollectionPtr const&, mongo::optimizer::QueryHints, boost::optional<mongo::BSONObj> const&, mongo::Pipeline const*, mongo::CanonicalQuery const*)","s+":"1B40"},{"a":"7F12E70E8D7C","b":"7F12E6D1F000","o":"3C9D7C","s":"_ZN5mongo34getSBEExecutorViaCascadesOptimizerERKNS_13CollectionPtrENS_9optimizer10QueryHintsEPKNS_14CanonicalQueryE","C":"mongo::getSBEExecutorViaCascadesOptimizer(mongo::CollectionPtr const&, mongo::optimizer::QueryHints, mongo::CanonicalQuery const*)","s+":"11C"},{"a":"7F12E71148D5","b":"7F12E6D1F000","o":"3F58D5","s":"_ZZN5mongo11getExecutorEPNS_16OperationContextERKNS_26MultipleCollectionAccessorESt10unique_ptrINS_14CanonicalQueryESt14default_deleteIS6_EESt8functionIFvPS6_bEENS_15PlanYieldPolicy11YieldPolicyERKNS_18QueryPlannerParamsEENKUlvE_clEv","C":"mongo::getExecutor(mongo::OperationContext*, mongo::MultipleCollectionAccessor const&, std::unique_ptr<mongo::CanonicalQuery, std::default_delete<mongo::CanonicalQuery> >, std::function<void (mongo::CanonicalQuery*, bool)>, mongo::PlanYieldPolicy::YieldPolicy, mongo::QueryPlannerParams const&)::{lambda()#1}::operator()() const","s+":"A25"},{"a":"7F12E7116604","b":"7F12E6D1F000","o":"3F7604","s":"_ZN5mongo11getExecutorEPNS_16OperationContextERKNS_26MultipleCollectionAccessorESt10unique_ptrINS_14CanonicalQueryESt14default_deleteIS6_EESt8functionIFvPS6_bEENS_15PlanYieldPolicy11YieldPolicyERKNS_18QueryPlannerParamsE","C":"mongo::getExecutor(mongo::OperationContext*, mongo::MultipleCollectionAccessor const&, std::unique_ptr<mongo::CanonicalQuery, std::default_delete<mongo::CanonicalQuery> >, std::function<void (mongo::CanonicalQuery*, bool)>, mongo::PlanYieldPolicy::YieldPolicy, mongo::QueryPlannerParams const&)","s+":"54"},{"a":"7F12E7116769","b":"7F12E6D1F000","o":"3F7769","s":"_ZN5mongo15getExecutorFindEPNS_16OperationContextERKNS_26MultipleCollectionAccessorESt10unique_ptrINS_14CanonicalQueryESt14default_deleteIS6_EESt8functionIFvPS6_bEEbNS_18QueryPlannerParamsE","C":"mongo::getExecutorFind(mongo::OperationContext*, mongo::MultipleCollectionAccessor const&, std::unique_ptr<mongo::CanonicalQuery, std::default_delete<mongo::CanonicalQuery> >, std::function<void (mongo::CanonicalQuery*, bool)>, bool, mongo::QueryPlannerParams)","s+":"D9"},

 Plan: 

[j0] plan : [1] project [s7 =
[j0]     let [
[j0]         l101.0 =
[j0]             if (exists(s3) || isObject({}))
[j0]             then setField({}, "c", s3)
[j0]             else {}
[j0]     ]
[j0]     in
[j0]         if (exists(s4) || isObject(l101.0))
[j0]         then setField(move(l101.0), "d", s4)
[j0]         else move(l101.0)
[j0] ]
[j0] [2] sort [s5, s6] [desc, desc] []
[j0] [2] project [s5 = (s3 ?: null), s6 = (s4 ?: null)]
[j0] [5] filter {(traverseF(s2, lambda(l101.0) { (move(l101.0) == 1L) }, false) ?: false)}
[j0] [6] filter {(traverseF(s1, lambda(l101.0) { (move(l101.0) == 1L) }, false) ?: false)}
[j0] [7] scan none none none none none none [s1 = a, s2 = b, s3 = c, s4 = d] @"3a0efe89-0ea1-4524-b5ba-0f4a645ea3fb" true false
a

 



 Comments   
Comment by Githook User [ 16/Mar/23 ]

Author:

{'name': 'Anna Wawrzyniak', 'email': 'anna.wawrzyniak@mongodb.com', 'username': 'anna-wawrzyniak'}

Message: SERVER-74641 Fix ambiguous compilation of SBE vm labels
Branch: master
https://github.com/mongodb/mongo/commit/12d6a66e432c74defdc91417e2c00a5251a36d5e

Comment by Anna Wawrzyniak [ 07/Mar/23 ]

Problem:
EExpressions compilation uses LabelScope to remove LabelInfo once its no longer needed to not pollute the collection.

The pattern that is used looks like this:

{
vm::CodeFragment code;
...
vm::LabelScope endLabel(code, ctx.newLabelId());
...
code.appendLabel(code)
return code;
}

where LabelScope calls "code.removeLabel" in destructor.

The expected behavior of that is like so:

endLabel = newLabelId
...
code.appendLabel(endLabel)
code.removeLabel(endLabel) // we want to remove endLabel from LabelInfo
return code

However, compiler appears to sometime choose to compile it more like:

endLabel = newLabelId
...
code.appendLabel(endLabel)
vm::CodeFragment tmp(std::move(code));
code.removeLabel(endLabel) //  called from LabelInfo destructor, but after the move copy occured. So removeLabel doesn't actually remove the label anymore.

The exception "Can't remove label that has outstanding fixups. labelId:1" is likely due to std::move(code) that results in code having non-empty label collection. As pointed out by Martin it might be the case that "InlinedVector(InlinedVector&& other)" move ctor may leave non-empty other collection in some cases.

The fix is to explicitly use removeLabel before return statement, so that we can ensure that removeLabel happens before any potential moves of code, regardless of compiler choices.

Generated at Thu Feb 08 06:28:02 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.