Windows Server 2012 won't unload DLL in a process - windows

I've created a program that creates a thread, loads a DLL there (LoadLibrary), calls one function in this DLL and unloads it using FreeLibrary.
LoadLibrary and FreeLibrary do not return any error codes, but ProcessHacket2 shows that this DLL still exists in memory. I've verified that my code does not reference this library.
After some time my code repeats these actions and another instance of this DLL appears in the process memory.
If my code will repeats these actions again and again a new instance will remain in RAM. Allocated virtual memory will growth.
I cannot repeat this problem on my development machine and other test computers. Only on one specific server.
It looks like (libmysql.dll):

Related

What's the lifetime of a DLL after being compiled?

I was reading about it and the part about memory was really confusing. What exactly happens to a DLL after compilation?
Questions that were somewhat bugging me:
Is it loaded into memory only once and all processes that require access to it are given only a pointer to where it is?
When is it loaded? I am sure it isn't just arbitrarily loaded into memory after compilation so is there a special procedure to load it or does Windows load a DLL when a process requires it and keeps it for sharing among other processes?
From the Microsoft docs
Every process that loads the DLL maps it into its virtual address space. After the process loads the DLL into its virtual address, it can call the exported DLL functions.
How does that "mapping" look like? I found that a bit confusing.
I don't know if this is a relevant piece of info but I am specifically interested in custom DLLs (DLLs written by me), not system DLLs
An exe file lists DLLs is wants to link to, so when the loader loads an exe, it loads DLLs that are listed as required, unless they are already loaded. A DLL may run initialization code the first time it loads.
Of course a DLL can be loaded dynamically by name, then it's loaded when the LoadLibrary API call is issued by a program. This is useful to implement dynamically loadable plugins.
Windows keeps a reference counter for each DLL, so when all processes stopped referencing a DLL, either by exiting or explicitly calling FreeLibrary, Windows will unload the DLL, giving it a chance to run any cleanup code.

Diagnosing Win32 RegisterClass leak

We are trying to troubleshoot a nasty problem on a production server where the server will start misbehaving after running for awhile.
Diagnostics have led us to believe there may be a bug in a DLL that is used by one of the processes running on this server that is resulting in a global atom leak. The assumed vector is a process that is calling RegisterClass without a corresponding UnregisterClass (and the class name is using a random number as part of the name, so it's a different class name each time the process starts).
This article provided some information: https://blogs.msdn.microsoft.com/ntdebugging/2012/01/31/identifying-global-atom-table-leaks/
But we are reluctant to attempt kernel mode debugging on a production server, so we have tried installing windbg and using the !gatom command to list atoms for a given session.
I use windbg to attach to a process in one of the sessions (these processes are running as Windows Services if that matters), then invoke the !gatom command. The returned atom list doesn't have any window classes in it.
Then I read this: https://blogs.msdn.microsoft.com/oldnewthing/20150429-00/?p=44984
and it sounds like there is a separate atom table for windows classes. And no way to query it. I was hoping that we'd be able to actually see how many windows class atoms have been registered, and see if that list gets bigger over time, indicating a leak.
The documentation on !gatom is sparse, and I'm hoping I can get some expert confirmation or recommendations on how to proceed.
Does anyone have any ideas on how we can get at the list of registered Windows classes on a production server?
More detail about what happens when the server starts to misbehave:
We run many instances (>50) of the same application as separately registered services running from isolated executables and DLLs - so each of those 50 instances has their own private executables and DLLs.
During their normal run, the processes unload and reload a DLL (about every hour). There is a windows class used that's part of a "session handle" used by the DLL (the session handle is part of the registered windows class name), and that session handle is unique each time the DLL is loaded. So every hour, there is an additional Window class registration, made by a DLL (our service stays running).
After some period of time, the system will get into a state where further attempts to load the DLL in question fail. This may happen for one of the services, then gradually over time, other services will start to have the same problem.
When this happens, restarting the service does not fix the problem. The only way that we've found to get things running properly again is to reboot the server.
We are monitoring memory commit load, and we are well within the virtual memory of the server. We are even within the physical memory size.
I just did a code review the vendor of the DLL, and it looks like they are not actually calling RegisterClass from the DLL itself (they only make one RegisterClass call from the DLL, and it's a static string - not a different class name for each session). The DLL launches an EXE, and that EXE is the one that registers the session specific class name. Their EXE does call UnregisterClass (and even if it didn't, the EXE is terminated when we unload their DLL, so it seems that this may not be what is going on).
I am now out of bullets on this one. The behavior seems like some sort of resource leak or pool exhaustion. The next time this happens, I will try connecting to the failing process with windbg and see what the application atom pool looks like - but I'm not hopeful that is going to shed any light.
Update: The excellent AtomTableMonitor tool has narrowed the problem to rogue RegisterWindowMessage. I'm going to ask a more specific question focused on this exact issue: Diagnosing RegisterWindowsMessage leak
You may try using this standalone global atom monitor
The application appears to have capabilities to monitor atoms in services
that run in a different session
btw if you have narrowed it to RegisterWindowMessage
then spy++ can log the Registered messages system wide along with thread and process
spy++ (i am using it from vs2015 community)
ctrl+m select all windows in system
in the messages tab clear all and select registered
and start logging
you can also save the log (it is plain text in-spite of strange extension )
powershell -c "gc spy++.sxl -Tail 3"
<000152> 001F01A4 P message:0xC1B2 [Registered:"nsAppShell:EventID"] wParam:00000000 lParam:06EDFCE0 time:4:2
7:49.584 point:(408, 221)
<000153> 001F01A4 P message:0xC1B2 [Registered:"nsAppShell:EventID"] wParam:00000000 lParam:06EDFCE0 time:4:2
7:49.600 point:(408, 221)
<000154> 001F01A4 P message:0xC1B2 [Registered:"nsAppShell:EventID"] wParam:00000000 lParam:06EDFCE0 time:4:2
7:49.600 point:(408, 221)

Where exactly do dll's get loaded? [duplicate]

This question already has answers here:
Questions Regarding DLL Loading in a Process Address Space
(2 answers)
Closed 8 years ago.
I'm sure this question has been asked multiple times, and I have read tons of articles, but I still don
t understand it. Where exactly does a DLL get loaded? I am talking about the actual code of the DLL. When I call, lets say, MessageBoxA, where does it jump to? Does the code get loaded into my own process, or does it jump somewhere else(not even sure if this is possible)?
Please enlighten me, this has been bothering me for quite some time, but I just can't seem to figure it out.
DLLs are loaded once per process. Here are some more details:
From Wikipedia:
DLLs execute in the memory space of the calling process and with the same access permissions
As described in this Stack Overflow answer:
A DLL is loaded at most once per process. So, if your DLL is used by multiple other DLLs, it still will exist once per process.
MSDN has plenty more details:
The system maintains a per-process reference count for each DLL. When a thread loads the DLL, the reference count is incremented by one. When the process terminates, or when the reference count becomes zero (run-time dynamic linking only), the DLL is unloaded from the virtual address space of the process.
Like any other function, an exported DLL function runs in the context of the thread that calls it. Therefore, the following conditions apply:
The threads of the process that called the DLL can use handles opened by a DLL function. Similarly, handles opened by any thread of the calling process can be used in the DLL function.
The DLL uses the stack of the calling thread and the virtual address space of the calling process.
The DLL allocates memory from the virtual address space of the calling process.
On Variable Scope:
Variables that are declared as global in a DLL source code file are treated as global variables by the compiler and linker, but each process that loads a given DLL gets its own copy of that DLL's global variables. The scope of static variables is limited to the block in which the static variables are declared. As a result, each process has its own instance of the DLL global and static variables by default.
Before DLLs are loaded, they have to be found. There are specific rules about how Windows searches for DLLs, such as those listed at Dynamic-Link Library Search Order.

Flow of execution of file in WINDOWS

My question is:
What is the flow of execution of an executable file in WINDOWS? (i.e. What happens when we start a application.)
How does the OS integrate with the application to operate or handle the application?
Does it have a central control place that checks execution of each file or process?
Is the process registered in the execution directory? (if any)
What actually happens that makes the file perform its desired task within WINDOWS environment?
All help is appreciated...
There's plenty going on beyond the stages already stated (loading the PE, enumerating the dlls it depends on, calling their entry points and calling the exe entry point).
Probably the earliest action is the OS and the processor collaborating to create a new address space infrastructure (I think essentially a dedicated TLB). The OS initializes a Process Environment Block, with process-wide data (e.g., Process ID and environment variables). It initializes a Thread Environment Block, with thread-specific data (thread id, SEH root handlers, etc). Once an appropriate address is selected for every dll and it is loaded there, re-addressing of exported functions happens by the windows loader. (very briefly - at compile time, the dll cannot know the address at which it will be loaded by every consumer exe. the actual call addresses of its functions is thus determined only at load time). There are initializations of memory pages shared between processes - for windows messages, for example - and I think some initialization of disk-paging structures. there's PLENTY more going on. The main windows component involved is indeed the windows loader, but the kernel and executive are involved. Finally, the exe entry point is called - it is by default BaseProcessStart.
Typically a lot of preparation happens still after that, above the OS level, depending on used frameworks (canonical ones being CRT for native code and the CLR for managed): the framework must initialize its own internal structures to be able to deliver services to the application - memory management, exception handling, I/O, you name it.
A great place to go for such in depth discussions is Windows Internals. You can also dig a bit deeper in forums like SO, but you have to be able to break it down into more focused bits. As phrased, this is really too much for an SO post.
This is high-level and misses many details:
The OS reads the PE Header to find the dlls that the exe depends on and the exe's entry point
The DllMain function in all linked dlls is called with the DLL_PROCESS_ATTACH message
The entry point of the exe is called with the appropriate arguments
There is no "execution directory" or other central control other than the kernel itself. However, there are APIs that allow you to enumerate and query the currently-running processes, such as EnumProcesses.
Your question isn't very clear, but I'll try to explain.
When you open an application, it is loaded into RAM from your disk.
The operating system jumps to the entry point of the application.
The OS provides all the calls required for showing a window, connecting with stuff and receiving user input. It also manages processing time, dividing it evenly between applications.

Unloading DLL from all processes after unhooking global CBT hook

How do you properly unload a DLL from all processes when the system-wide hook that loaded them gets unloaded?
From MSDN:
You can release a global hook
procedure by using
UnhookWindowsHookEx, but this function
does not free the DLL containing the
hook procedure. This is because global
hook procedures are called in the
process context of every application
in the desktop, causing an implicit
call to the LoadLibrary function for
all of those processes. Because a call
to the FreeLibrary function cannot be
made for another process, there is
then no way to free the DLL. The
system eventually frees the DLL after
all processes explicitly linked to the
DLL have either terminated or called
FreeLibrary and all processes that
called the hook procedure have resumed
processing outside the DLL.
So what I am looking for, is a method to detect when the hook is unhooked, and then call FreeLibrary from all the processes that were hooked. Are there any other ways to cause instant unloading of a DLL when the hook is unloaded?
Hook dll are unloaded in their message loop. Forcing them to pass in the message loop help to unload them.
Add this after your UnhookWindowsHookEx to force all message loops to wake up :
DWORD dwResult;
SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);
However I still have the issue from time to time. I don't know where it's coming from. I suppose a locked process could prevent the dll to unload, but I have no proof of that.
In general you should use global windows hooking if FreeLibrary is not a required be called. If you do want to do this you can use DLL injection (see for example http://www.codeproject.com/KB/threads/winspy.aspx and http://www.codeproject.com/KB/system/hooksys.aspx) with respect of CreateRemoteThread and LoadLibrary technique. In the case you can do what you want in the remote process. You can combine both techniques.
If you want call FreeLibrary only to do an update of the DLL you can do this in another way. Every DLL which is loaded could be renamed (in cmd.exe for example) to a temporary name and you can call MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT flag. Then you can already copy and use new version of the DLL. The old one DLL will be deleted at the next reboot of computer.

Resources