mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-26 06:43:15 +08:00
revert(windows): drop the TLS thread-heap release
Reverts the #581 fix mechanism, not the diagnosis. main's dry run passes both windows-11-arm shards and test-windows-guards; this branch fails all three. The only change here that affects process LOAD is the .CRT$XLB detach callback, and the arm64 failures are load-time crashes (STATUS_ILLEGAL_INSTRUCTION, pass=0, secs=0, five suites in the same second) -- while the guards exercise many launcher and payload spawns. The same binary loads fine on a UTM arm64 VM, so the placement is tolerated by some loaders and not others, which is not something to ship on a supported platform. #581's root cause stands and is documented: a static MinGW link has no DllMain and registers no TLS callback, so mi_thread_done never runs and every thread leaks its heap (607 heaps after 300 requests, 170 MiB against ~300 KiB live). The delivery mechanism needs to be one the loader accepts everywhere -- an FLS callback registered at runtime is the obvious candidate, with no linker section placement involved. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
@@ -7,10 +7,6 @@
|
||||
#include "foundation/constants.h"
|
||||
#include "foundation/compat_thread.h"
|
||||
|
||||
#include "foundation/platform.h"
|
||||
|
||||
#include <mimalloc.h> /* mi_thread_done at thread exit */
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@@ -28,50 +24,6 @@ typedef struct {
|
||||
void *arg;
|
||||
} win_thread_arg_t;
|
||||
|
||||
/* Release each thread's allocator heap at DLL_THREAD_DETACH.
|
||||
*
|
||||
* Doing this from the thread wrapper instead crashes: the wrapper returns
|
||||
* before the CRT's own thread teardown, and abandoning the heap there raced
|
||||
* with frees still in flight (daemon_ipc_wait_forever_is_interruptible
|
||||
* segfaulted, rc=139, reproducibly and only with the release enabled). A TLS
|
||||
* callback is the mechanism mimalloc itself uses under MSVC and runs after all
|
||||
* other thread cleanup, which is the only point where the heap is genuinely
|
||||
* unreferenced.
|
||||
*
|
||||
* Without any of this, a static MinGW link -- no DllMain, no TLS callback --
|
||||
* never releases a thread heap at all: 607 heaps after 300 requests, 170 MiB
|
||||
* held against a ~300 KiB live set, growing without bound (#581). POSIX gets
|
||||
* this from a pthread TSD destructor, which is why only Windows leaked.
|
||||
*
|
||||
* CBM_MI_THREAD_DONE=0 disables it, so one binary can demonstrate both
|
||||
* behaviours rather than requiring a rebuild to establish causality. */
|
||||
static bool thread_release_heap_enabled(void) {
|
||||
static int state = -1;
|
||||
if (state < 0) {
|
||||
char buf[CBM_SZ_16];
|
||||
state =
|
||||
(cbm_safe_getenv("CBM_MI_THREAD_DONE", buf, sizeof(buf), NULL) != NULL && buf[0] == '0')
|
||||
? 0
|
||||
: 1;
|
||||
}
|
||||
return state == 1;
|
||||
}
|
||||
|
||||
static void NTAPI cbm_thread_detach_callback(PVOID handle, DWORD reason, PVOID reserved) {
|
||||
(void)handle;
|
||||
(void)reserved;
|
||||
if (reason == DLL_THREAD_DETACH && thread_release_heap_enabled()) {
|
||||
mi_thread_done();
|
||||
}
|
||||
}
|
||||
|
||||
/* Park the callback in .CRT$XLB, the table the loader walks. The linker only
|
||||
* emits a TLS directory when _tls_used is referenced, so anchor it. */
|
||||
extern const IMAGE_TLS_DIRECTORY64 _tls_used;
|
||||
static const void *const cbm_tls_anchor __attribute__((used)) = &_tls_used;
|
||||
__attribute__((section(".CRT$XLB"), used)) PIMAGE_TLS_CALLBACK cbm_thread_detach_tls_cb =
|
||||
cbm_thread_detach_callback;
|
||||
|
||||
static DWORD WINAPI win_thread_wrapper(LPVOID lpParam) {
|
||||
win_thread_arg_t *a = (win_thread_arg_t *)lpParam;
|
||||
void *(*fn)(void *) = a->fn;
|
||||
|
||||
Reference in New Issue
Block a user