FreeLibrary returns true indefinitely

别说谁变了你拦得住时间么 提交于 2020-01-24 00:40:17

问题


Is there any reason why FreeLibrary would repetitively return true?

I'm trying to unload some native dll from my process, so I'm getting it's handle and then calling FreeLibrary until the ref count goes to zero and so FreeLibrary returns false... but it never does:

IntPtr pDll = DllLoadingImports.LoadLibrary(dllTounLoad);
//throw if pDll == IntPtr.Zero
while(DllLoadingImports.FreeLibrary(pDll));

The code runs and never returns. Also the process explorer shows the dll still loaded.

More background:

I'm trying to unload native library loaded by use of DllImport and I'm using trick described here: https://stackoverflow.com/a/2445558/2308106 It's for prototyping purposes so I don't have to care about possible consequnces... but I'm puzzled why the library won't unload

Edit 1: I found that similar behavior can be achieved by specifying GET_MODULE_HANDLE_EX_FLAG_PIN flag in GetModuleHandleEx function (which can be called from within DllMain on dll load).

The dll I'm trying to unload is python.dll (more precisely python36.dll). But haven't found usage of this flag within python source code. DllMain itself is empty.

Edit 2: I was asked for minimum executable example - so here it goes: It uses pythonnet library (version 2.3.0) - that's the PythonEngine calls.

[TestFixture]
public class PythonUnloadTest
{
    public static class DllImports
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }

    [Test]
    public void PythonLoadUnload()
    {
        const string PythonDll = @"PythonEngine\python36";

        PythonEngine.Initialize();
        //locking etc not included for simplicity

        //Replace module with 'sys' (or some others) and dll can be unloaded
        var module = PythonEngine.ImportModule("numpy");
        module.Dispose();

        IntPtr pythonDllHandle = DllImports.LoadLibrary(PythonDll);
        if (pythonDllHandle == IntPtr.Zero)
        {
            throw new Exception("Dll not loaded");
        }

        for (int i = 0; i < 100000; i++)
        {
            if (!DllImports.FreeLibrary(pythonDllHandle))
            {
                return;
            }
        }

        Assert.Fail("Python not unloaded");
    }
}

Regardless of this specific case (python and pythonnet and loading of numpy) - there still needs to be some phenomenon that prevents process from being able to unload dlls by calling FreeLibrary. I'm suspecting instalment of some hooks or calling GetModuleHandleEx with above mentioned flag... I'll try to inspect numpy source. But if there are any specific tips what should I be looking for - I'd appreciate those


回答1:


Is there any reason why FreeLibrary would repetitively return true?

As I already put in edits - there can be few reasons:

  • Specifying GET_MODULE_HANDLE_EX_FLAG_PIN flag in GetModuleHandleEx function. Module can even call this on itself in it's DllMain - rendering self unloadable.
  • Installing hooks. Module M, that installs hooks won't be unloaded untill process exits. Sources - e.g.: https://msdn.microsoft.com/en-us/library/ms644960(v=VS.85).aspx#system_events or https://blogs.msmvps.com/vandooren/2006/10/09/preventing-a-dll-from-being-unloaded-by-the-app-that-uses-it/


来源:https://stackoverflow.com/questions/48631560/freelibrary-returns-true-indefinitely

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!