ExportXMLWordPrintableJSON

    • 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.

            Assignee:
            Sergei Bazhenov
            Reporter:
            Sergei Bazhenov
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: