开发者

Sharing some info with all DLLs pulled into a process

We've got an Enterprise system which has many processes (EXEs, services, DCOM servers, COM+ 开发者_如何学运维apps, ISAPI, MMC snapins) all of which make use of many COM components. We've recently seen failures in some of the customer deployments, but are finding it hard to troubleshoot the cause.

In order to track down the problem, we've augmented the entire source with logging statements where errors occur.

In order to identify which logs came from what processes, the C++ logging code (compiled into all components) uses the EXE name to name the log. This is good for some cases, but not all - COM+ apps, ISAPI and MMC snapins all have system EXE names and the logs end up interleaved.

I saw this post about shared data sections which might help, but what I don't understand is who decides what goes in the shared section. Is there any way I can guarantee that a particular piece of code writes into the shared section before anyone else reads it?

Or is there a better solution to this problem?


To synchronize multiple processes writing to the shared section you'd need some kind of IPC e.g. Windows events, mutexes, sockets. Each of your modules calls CreateMutex and passes a fixed name which all the modules share. Modules then call WaitForSingleObject to wait and claim the mutex - when one of them gets it, it can read/write the shared section while every other module waits. When its done it calls ReleaseMutex to let another module have a go.

Having said all that personally I'd persevere with the log files. I'm guessing your problem is that for DLLs you're basing your log file name on the parent process EXE name instead of the DLLs own name?

You can get a DLLs own name by storing the DLL instance handle you get passed in DllMain, and then using it with GetModuleFileName. Note this works for EXEs as well if you leave the instance handle as NULL.

// global variable to store DLL handle (or it stays NULL if this is an EXE)
HINSTANCE hDllHandle=NULL;

BOOLEAN WINAPI DllMain( IN HINSTANCE hInstance, 
     IN DWORD     nReason, 
     IN LPVOID    Reserved )
{
  hDllHandle = hInstance;
  return TRUE;

}

<snip>

void Log(LPSTR lpszMsg)
{
    WCHAR szMyModuleName[MAX_PATH]={0};

    // if hDllHandle is still NULL (e.g. this is an EXE) it returns the process name
    // if non-NULL, it returns our DLL name
    GetModuleFileName(hDllHandle, szMyModuleName, MAX_PATH);

    fprintf(LOGFILE, "[%s] %s\n", szMyModuleName, lpszMsg);

     ....<snip>....
}


Usage of a shared section in a DLL (section with the RWS flags) don't really solve your main problem. If you need a shared memory for quick communication between processes you can use memory mapped files (see http://msdn.microsoft.com/en-us/library/ms810613.aspx for example) and have more control over creating and usage of the shared memory.

To receive more about the process which loaded your DLL you can log additionally a command line of the application (GetCommandLine() function for example). You will see something like "C:\Windows\system32\mmc.exe C:\Windows\system32\services.msc" or "C:\Windows\system32\mmc.exe C:\Windows\system32\azman.msc" for MMC snapins.

To see more information about calling process you can you StackWalk64 (see http://msdn.microsoft.com/en-us/library/ms680650(VS.85).aspx) function. See http://stackwalker.codeplex.com/ or http://www.codeproject.com/KB/threads/StackWalker.aspx for a good code example.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜