]> git.ipfire.org Git - thirdparty/squid.git/commit - src/Transients.cc
Do not use static initialization to register modules (#1422)
authorAlex Rousskov <rousskov@measurement-factory.com>
Fri, 14 Jul 2023 17:46:30 +0000 (17:46 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Sun, 16 Jul 2023 21:42:32 +0000 (21:42 +0000)
commit230d44101b32f49466265b3c3dd7c9b9e6b96763
tree900daf3278126648fb4d6f497d2b59a9bba369e4
parenta93bb15bb4576411da0402d37abb1f735d0c723d
Do not use static initialization to register modules (#1422)

    ERROR: ... Unknown authentication scheme 'ntlm'.

When a translation unit does not contain main() and its code is not used
by the rest of the executable, the linker may exclude that translation
unit from the executable. This exclusion by LTO may happen even if that
code _is_ used to initialize static variables in that translation unit:
"If no variable or function is odr-used from a given translation unit,
the non-local variables defined in that translation unit may never be
initialized"[^1].

[^1]: https://en.cppreference.com/w/cpp/language/initialization

For example, src/auth/ntlm/Scheme.o translation unit contains nothing
but NtlmAuthRr class definition and static initialization code. The
linker knows that the rest of Squid does not use NtlmAuthRr and excludes
that translation unit from the squid executable, effectively disabling
NTLM module registration required to parse "auth_param ntlm" directives.

The problem does affect existing NTLM module, and may affect any future
module code as we reduce module's external footprint. This change
converts all RegisteredRunner registrations from using side effects of
static initialization to explicit registration calls from SquidMain().
Relying on "life before main()" is a design bug. This PR fixes that bug
with respect to RegisteredRunner registrations.

Due to indeterminate C++ static initialization order, no module can
require registration before main() starts. Thus, moving registration
timing to the beginning of SquidMain() should have no negative effects.

The new registration API still does not expose main.cc to any module
details (other than the name of the registration function itself). We
still do not need to #include any module headers into main.cc. Compiler
or linker does catch most typos in RegisteredRunner names.

Unfortunately, explicit registration still cannot prevent bugs where we
forget to register a module or fail to register a module due to wrong
registration code guards. Eventually, CI will expose such bugs.
17 files changed:
src/CollapsedForwarding.cc
src/DiskIO/IpcIo/IpcIoFile.cc
src/MemStore.cc
src/PeerPoolMgr.cc
src/Transients.cc
src/auth/ntlm/Scheme.cc
src/base/RunnersRegistry.cc
src/base/RunnersRegistry.h
src/cache_cf.cc
src/client_db.cc
src/dns_internal.cc
src/esi/ExpatParser.cc
src/esi/Libxml2Parser.cc
src/fs/rock/RockSwapDir.cc
src/ipc/mem/Pages.cc
src/main.cc
src/security/Session.cc