<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/154361>154361</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            `libclang.dll` crashes process on exit when unloaded
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          mrexodia
      </td>
    </tr>
</table>

<pre>
    If you unload the latest `libclang.dll` from https://github.com/llvm/llvm-project/releases/download/llvmorg-21.1.0-rc3/LLVM-21.1.0-rc3-win64.exe (also happens for 20.x) the process crashes on exit. Minimal reproduction:

```cpp
#include <Windows.h>

int main() {
    auto libclang = LoadLibraryW(L"libclang.dll");
 FreeLibrary(libclang);
}

```

Here is a screenshot of a crash on Windows Sandbox (Windows 10 Pro 22H2 19045.6216), nothing installed (notably no MSVC runtime at all):

<img width="1522" height="789" alt="Image" src="https://github.com/user-attachments/assets/4b06239e-782f-4a97-a6ce-92a5516b6c53" />

The crash is a DEP violation trying to execute a nonexistent region. This happens because the atexit function passed to `FlsAlloc` ceases to exist when you unload the DLL. Cross referencing this function on module load shows the following code:

<img width="1522" height="789" alt="Image" src="https://github.com/user-attachments/assets/7499f152-749f-4591-9bce-74b62e103eaa" />

You are expected to call `FlsFree` for all the slots during `DllMain` with the `DLL_PROCESS_DETACH` reason. Searching the LLVM codebase for `FlsAlloc` shows two occurrences:

- https://github.com/llvm/llvm-project/blob/d0dc3799b70bb6b51ed2e90b93f8ea5d4f30cef1/libcxx/src/support/win32/thread_win32.cpp#L199
- https://github.com/llvm/llvm-project/blob/d0dc3799b70bb6b51ed2e90b93f8ea5d4f30cef1/llvm/lib/Support/rpmalloc/rpmalloc.c#L3244

Looking at the disassembly around the `FlsAlloc` I see `OpenProcessToken`, which matches `rpmalloc`. There is an `FlsFree` in there, but it does not appear to be called correctly on `DLL_PROCESS_DETACH`.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzMVl1v27gS_TX0y8ACRX1ZD35I4xgt4KDBTdDiPhUUObJ4S5ECSdXOv78Y2U67we4CfVksYMDiiJwZnnN4KBmjOTrELas-sGq3knMafNiOAc9eG7nqvH7dfurh1c8wO-ulhjQgWJkwJmA1t6ZTVrpjpq1lNYc--BGGlKbIijsm9kzsjyYNc5cpPzKxt_bH7W89Bf8_VImJfUCLMmJkYq_9aalzneTDcS3yLM_4OqiCif3h8OXxl8j6ZFxdZnhGYGIjbfQwyGlCF6H3AQTPzky0S9NT8ApjBBVkHDCCd4BnkzJ4NM6M0kLAKXg9q2S8o-758qv55aemiYaiME7ZWSOw4v6rcdqfYjaw4uEy3bgEozSOiQ3VZc0Hxu8AAOScPNzQAlbs4OClPpguyPD6lYnNgQnxBzSFYKJlxZJgHxCvc5nY3Ka9vWfN7l23l-FHDAgmgoSoAqKLg0_ge5AXEAiC6xbgWTrd-TOheAvlHJ6CByE-CshbXlZZLfKaiop7cD4Nxh3BuJiktahppfNJdvYVnIfH5y_3EGaXzIggE0jaUfsT1uLejEc4GZ0GVuyYEHlFGxYwoDkO6RJrNi2FpL2OP43yiBSJQV0ifyO1OWJYy5SkGkZ0icQlY8Tloex4LYoW181G9OtSts1a1grXrZBVldddraqC6lDaG7UvA15hWxDdPTzBD-OtJLlACq-ERvKAZ1RzQpDgvMOziQldgoBH410GL4OJbwrtUMk54qJOmUiM0M9u0R9M1KumhKzmexvvrPWKTphaTsqlkokJTgO69-dzdzhkcB98jBCwx4BOLd1R8bcK3sHo9WwRlnVxIM5pde-t9SdaoLzGfwtlTdm2fV6JdVO2_bqs2nzddgrXTdnVAnNeoJTvKfuvn0EGBDxPqNIFTiWtvWJKp2oxLR9In8vmo_Upgp4D7Z_VfGftI53nmsPJpGGZQ-HD4dvTfz7fPzw_f9s9vNzdf6QZAWUklp9RBjVcIEcgy1qg7GTEpdg7Sq_Qnzx4peZAdGF8w339-37aWd-Rl3KtiqZtu4Z3Xd1VOWqBLe_aot-grHTZF1xhn1MC06nzmYk90ST2cZ4mHyjVybhCMLFPQ0Cpvy3DjLxQFIe8bf-x_q55DK17fusuTKNcUPz5mClqrRBleYHv4P13YkKmhQxtIklqJJuSwc9O3yj9lZFPEHEJfp7QPV0ujhf_HUkH5H6nwagBRpkU3SSs5m-N1JwO-c133TulGUfVAlKObk5gEmiPkdwUyBRkIIl2uKgUNSgfAqpkX-m0_pXsspXeFrotWrnCbd5UVZ3XTc1Xw1b2DRd502rJi1Z0iE3b1GVeFE3Xl5XgK7MVXFR8k7d5lbeCZ7wvNl2rN4LnvBJaspLjKI3NiIDMh-PKxDjjNq_Kos5XVnZo4_L1IITDEyxv6eqqdquwXWjv5mNkJbcmpvgzTTLJ4vZPviBu1_Ptur5e0xefu3gc6tUc7Pa3Zbc0R15y7f7HVvw_AAD__6vh2xw">