簡體   English   中英

卸載 NativeAOT 編譯 dll

[英]Unloading NativeAOT compiled dll

用.NET 7的NativeAOT編譯。 我們現在可以加載 C# dll 作為常規 Win32 模塊。

HMODULE module = LoadLibraryW("AOT.dll");
auto hello = GetProcAddress(module, "Hello");
hello();

這工作正常並在控制台中打印一些東西。

但是,卸載dll的時候,根本就不行。 無論我調用FreeLibrary("AOT.dll")多少次, GetModuleHandle("AOT.dll")仍然返回模塊的句柄,這意味着它沒有成功卸載。

我的“瘋狂猜測”是運行時有一些后台線程仍在運行(GC?),所以我枚舉了所有線程並使用NtQueryInformationThread來檢索每個線程的起始地址,然后使用GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS調用GetModuleHandleEx以獲取線程啟動的模塊,結果如下。

前:

THREAD ID      = 7052
base priority  = 8
delta priority = 0
Start address: 00007FF69D751613
Module: 00007FF69D740000 => CppRun.exe


THREAD ID      = 3248
base priority  = 8
delta priority = 0
Start address: 00007FFEF1F42B20
Module: 00007FFEF1EF0000 => ntdll.dll


THREAD ID      = 7160
base priority  = 8
delta priority = 0
Start address: 00007FFEF1F42B20
Module: 00007FFEF1EF0000 => ntdll.dll

后:

THREAD ID      = 7052
base priority  = 8
delta priority = 0
Start address: 00007FF69D751613
Module: 00007FF69D740000 => CppRun.exe


THREAD ID      = 3248
base priority  = 8
delta priority = 0
Start address: 00007FFEF1F42B20
Module: 00007FFEF1EF0000 => ntdll.dll


THREAD ID      = 7160
base priority  = 8
delta priority = 0
Start address: 00007FFEF1F42B20
Module: 00007FFEF1EF0000 => ntdll.dll


THREAD ID      = 5944
base priority  = 8
delta priority = 0
Start address: 00007FFEF1F42B20
Module: 00007FFEF1EF0000 => ntdll.dll


THREAD ID      = 17444
base priority  = 10
delta priority = 0
Start address: 00007FFE206DBEF0
Module: 00007FFE206D0000 => AOT.dll

“CppRun.exe”是我的測試應用程序。

如您所見,生成了兩個額外的線程。 一個來自 ntdll (5944),一個來自我的 AOT 編譯 dll (17444)。

我不知道“AOT.dll”中剩余的線程是做什么用的(也許是 GC?),但我成功地強制終止了它(我知道這絕對是不健康的)。

但是,當我嘗試在 ntdll (5944) 中打開線程時,它會拋出異常

為此操作指定了一個無效的線程,句柄 %p。 可能指定了線程池工作線程

鑒於此,我假設 .NET 在初始化期間啟動了一個線程池工作者? 如何停止該池並卸載 dll?

或者,是否有更好的方法來卸載 NativeAOT 編譯的 dll?

更新:我已經連接了CreateThreadPool function,但運行時沒有調用它。 仍在試圖弄清楚是什么產生了那個線程。

編輯:

NativeAOT(aka CoreRT)編譯的 dll 一開始是無法加載的,但微軟后來由於 memory 泄漏和進程退出崩潰而阻止了該功能。 有關詳細信息,請參閱此 PR 這個答案只是使用繞行鈎子恢復功能,不處理 memory 泄漏或崩潰 需要您自擔風險使用它。

我能夠通過手動釋放由 .NET 創建的 FLS(光纖本地存儲)來防止訪問沖突崩潰。 是一個簡單的演示。

原回答如下:

原來線程被 Windows 10 用於並行庫加載(TppWorkerThread),這不是問題所在。

我最終使用這個方便的工具檢查了 winapi 調用,發現 .NET 正在使用GET_MODULE_HANDLE_EX_FLAG_PIN標志調用GetModuleHandleEx ,從而阻止模塊卸載。 .NET 調用 GetModuleHandleEx

所以我連接了GetModuleHandleEx來攔截調用並移出標志。 噠噠。 現在我可以毫無問題地卸載 NativeAOT 編譯的 dll。

我知道這種方法很老套,但是,嘿,它有效。 如果有人碰巧有更好的解決方案,請告訴我。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM