Bug (High Severity): Wrong queue type in MemDiscardCallstack
In the callstack path of MemDiscardCallstack, the wrong queue type is
sent:
SendMemDiscard( QueueType::MemDiscard, thread, name );
Every other callstack variant correctly uses its callstack queue type
(MemAllocCallstack, MemFreeCallstack, etc.), but this one uses the
non-callstack type. The SendMemDiscard assertion at line 1026 confirms
MemDiscardCallstack is a valid value.
Impact: The callstack captured by SendCallstackSerial() will be orphaned.
The server processes the event via the non-callstack handler, leaving the
callstack serial data unconsumed, which desynchronizes the serial queue
and corrupts all subsequent events.
A zone emitted from a shared object initializer runs before the
executable's constructors, so its timestamp precedes s_initTime, which
the server uses as the trace epoch (baseTime). Such a zone converts to
negative trace time and its end no longer satisfies IsEndValid(), which
excludes it from statistics reconstruction and makes it render as
never-ending.
Record the current time when a producer token is created before
s_initTime is constructed and use it as the init time, ensuring no event
timestamp precedes the trace epoch.
ELF init_priority only orders constructors within a single module. All of
a shared object's initializers run before any of the executable's, so an
instrumented dependency .so emitting a zone from its static initializer
creates the main thread producer token against the zero-initialized
s_queue. The queue constructor then resets the producer list, orphaning
that producer: every zone emitted on the main thread from that point on
is enqueued into blocks no consumer ever iterates and silently lost,
while sampling (worker thread producer) keeps working.
Re-link such a producer right after the queue is constructed. In the
common case, where nothing was emitted during shared object init, this
merely constructs the main thread token eagerly.
OLDNAMES.lib may not be linked if you use /NODEFAULTLIB.
Note: This uses `_MSC_VER` as a gate and not _WIN32 as MinGW apparently uses `fileno` and not `_fileno`.
Extension point so private/unsupported platforms can plug in their own implementations of the kernel/libc primitives Tracy depends on, without patching the `#if`/`#elif` chains.
Projects supply a platform header via `-DTRACY_PLATFORM_HEADER="\"my_platform.h\""` at build time. Tracy includes it in any TU that needs the hooks. The header toggles per-category `TRACY_HAS_CUSTOM_*` macros and declares matching `tracy::Platform*` functions.
Available hooks:
- `TRACY_HAS_CUSTOM_THREAD_ID` → `PlatformGetThreadId`
- `TRACY_HAS_CUSTOM_USER_INFO` → `PlatformGetHostname`, `PlatformGetUserLogin`, `PlatformGetUserFullName`
- `TRACY_HAS_CUSTOM_SAFE_COPY` → `PlatformSafeMemcpy`
- `TRACY_HAS_CUSTOM_ALLOCATOR` → `PlatformMalloc`, `PlatformFree`, `PlatformRealloc`, `PlatformAllocatorInit`, `PlatformAllocatorThreadInit`, `PlatformAllocatorFinalize`, `PlatformAllocatorThreadFinalize`
Each hook is wired as the first arm of its respective `#if`/`#elif` chain, so existing supported platforms are unaffected.
Template files in `examples/CustomPlatform/` and a new subsection in `manual/tracy.tex` document the mechanism.
The function is about to dispatch between rpmalloc and a pluggable allocator hook, so the rpmalloc-specific name no longer fits. Pure rename plus a small consequence: the SymbolWorker call site no longer needs the TRACY_USE_RPMALLOC guard, since the no-op static-inline fallback in TracyAlloc.hpp makes InitAllocator() safe to call unconditionally.
Replace `#ifdef BSD` (which requires including `<sys/param.h>` first) with explicit checks for `__FreeBSD__`, `__NetBSD__`, `__OpenBSD__` and `__DragonFly__`, matching how these BSDs are already enumerated elsewhere in the codebase (OS name strings, thread id helpers, etc.).
This also avoids leaking the `sys/param.h` requirement through public headers (`TracySysTime.hpp`, `TracyCallstack.h`), where consumers would otherwise need it to correctly see `TRACY_HAS_SYSTIME` / `TRACY_HAS_CALLSTACK`.
`libbacktrace/config.h` is left as-is — it's third-party and only included from .c files where the `BSD` macro can still be picked up locally.
Note: for `setsockopt( m_sock, IPPROTO_IPV6, IPV6_V6ONLY, (const char*)&val, sizeof( val ) );` I added `__APPLE__` too since this was the only place where it was not checked explicitely.
The end address is now readily available in lower_bound search, instead
of needing to be calculated constantly in the lambda.
The size can be equivalently calculated from the end address, but this
only happens once, after the symbol is found.
After investigating (downloading and installing) all publicly available SDKs at https://learn.microsoft.com/en-us/windows/apps/windows-sdk/downloads-archive I concluded the `TRACEHANDLE` deprecation started in `10.0.26100`.
This defines `PROCESSTRACE_HANDLE` and `CONTROLTRACE_ID` as done by the SDK when using older versions. Using `WDK_NTDDI_VERSION` (and not `NTDDI_VERSION` which may change based on `_WIN32_WINNT` or user input seems to be the most reliable way to do it. While it says "WDK" it's been part of the SDK in `shared\sdkddkver.h`. Note it doesn't work for MinGW because it updates half of its sdk files for some reason.
Tested with both 10.0.26100 and 10.0.22621.0 which is the last one I found without the new types.
Also changes CONTROLTRACE_ID to ULONG64 on mingw which is correct (type used by `TRACEHANDLE` too in mingw fe2763863a/mingw-w64-headers/include/evntrace.h (L60) )