-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Major - P3
-
None
-
Affects Version/s: None
-
Component/s: None
-
Networking & Observability
-
ALL
-
v8.0
-
N&O 2026-10-12, N&O 2026-10-26
-
200
-
None
-
None
-
None
-
None
-
None
-
None
-
None
Problem
Unit tests that link //src/mongo/db:service_context but neither //src/mongo/transport:transport_layer_common nor the lock manager fail to link in static UBSAN builds:
ld.lld: error: undefined symbol: typeinfo for mongo::transport::Session ld.lld: error: undefined symbol: typeinfo for mongo::Locker
On v8.0 this breaks unit_test_group3 and unit_test_group7 on rhel8-debug-ubsan on every run since 2026-07-23 (//src/mongo/s/commands:document_shard_key_query_conversion_test, //src/mongo/db/repl:db_repl_worker_pool_thread_count_test; BF-45293, BF-46718). Master has the same defect; it is only invisible there because master's static UBSAN variants do not link unit tests.
Cause
transport::Session and Locker are used from below the libraries that implement them: Client/ServiceContext/OperationContext (service_context) call through Session*, OperationContext owns the Locker, and WriteUnitOfWork calls Locker::begin/endWriteUnitOfWork. Some of their methods were made virtual only to avoid naming the implementing library (Session::setInOperation, Locker::~Locker, Locker::begin/endWriteUnitOfWork). But each class has an out-of-line virtual function (its key function), so its type info is emitted only in the implementing library: session.cpp in transport_layer_common and locker.cpp in lock_manager, both of which depend on service_context. With -fsanitize=vptr (on in static UBSAN builds; dynamic builds turn it off, see SERVER-49798) every virtual call through those types references their type info, so the hidden dependency on a library above service_context becomes a real link dependency. TransportLayer and SessionManager are used the same way without problems because they have no key function.
Fix
- transport::Session: session.cpp only needs //src/mongo:base and //src/mongo/util:fail_point, so it moves into a new //src/mongo/transport:session library that both service_context and transport_layer_common depend on. Session::setInOperation no longer needs to be virtual.
- Locker: its implementation needs the lock manager, so it cannot move down. Instead OperationContext and WriteUnitOfWork see only a new LockerBase interface (inline virtual destructor, pure beginWriteUnitOfWork/endWriteUnitOfWork) that Locker (now final) implements. OperationContext stores a std::unique_ptr<LockerBase>; the accessors that return Locker are inline so the downcast is compiled into their callers. LockerBase goes away with SERVER-77213.
No behavior change: the same Locker methods run, still through virtual dispatch.
- is related to
-
SERVER-133954 Declare missing lock_manager dependencies in Bazel unit-test targets
-
- Closed
-
-
SERVER-49798 Enforce correct library graph for ubsan vptr check builds
-
- Closed
-