|
|
|
date: Wed, 16 Apr 2008 01:11:06 -0700,
group: microsoft.public.win32.programmer.wmi
back
WMI server process leak using refreshers
Hi,
We found a memory leak problem in WMI while refreshing some high
performance data in remote systems with Windows Vista or Windows Server 2008
from a Windows XP system.
We made a test program based on your example in Accessing Performance Data
in C++ http://msdn2.microsoft.com/en-us/library/aa384724(VS.85).aspx to show
the memory use of the WMI remote service, the code of that program is
included below on this post.
The main difference with the official example is related about the
security used to connect to a remote system, because the example didn't work
for us while trying to monitor a remote machine. Other difference is that we
do not get the objects refreshed, we only call the Refresh() method. The last
difference is that we have two loops, one only for refreshes and one for the
full process to emulate some different scenarios
When we try to do only refreshes, the Commit Size value of the remote WMI
server process starts to grow slowly until all the refreshes are done, then
the server process dissapears abruptly after a while.
When we try to loop the full process, then the Commit Size of the server
process grows very fast, reaching hundredths of MB in seconds and then, when
the process in near 512 MB, the test application starts to receive the error
0x80004005 (Unspecified error) for each single operation. Some time later,
the error changes to 0x8007046a (Not enough server storage is available to
process this command.), 0x80041006 (There was not enough memory for the
operation) or 0x800700a4 (No more threads can be created in the system) for
every operation until the application ends.
If I run the same tests targetting a Windows XP system, the WMI server
process doesn't show any increase in the Commit Size.
Regards,
Tango
The test code is the following, need to replace the values of the user,
password and remote namespace in order to work
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
#define NUMBER_OF_REFRESHES 1
#define NUMBER_OF_FULL_LOOPS 1
#define NAME_SPACE L"\\\\Remote_System\\root\\cimv2"
#define DOMAIN L"Domain"
#define USER L"User"
#define FULL_USER L"Domain\\User"
#define PASSWORD L"Password"
int __cdecl wmain(int argc, wchar_t* argv[])
{
HRESULT hr = S_OK;
IWbemRefresher *pRefresher = NULL;
IWbemConfigureRefresher *pConfig = NULL;
IWbemHiPerfEnum *pEnum = NULL;
IWbemServices *pNameSpace = NULL;
IWbemLocator *pWbemLocator = NULL;
IUnknown *pUnkServ = NULL;
SEC_WINNT_AUTH_IDENTITY_W *pAuthIdentity = NULL;
BSTR bstrNameSpace = NULL;
BSTR bstrUserName = NULL;
BSTR userbstr = NULL;
BSTR domainbstr = NULL;
BSTR bstrPassword = NULL;
long lID = 0;
long lVirtualBytesHandle = 0;
long lIDProcessHandle = 0;
DWORD dwVirtualBytes = 0;
DWORD dwProcessId = 0;
DWORD dwNumObjects = 0;
DWORD dwNumReturned = 0;
DWORD dwIDProcess = 0;
DWORD i=0;
int x=0;
int y=0;
for(y = 0; y < NUMBER_OF_FULL_LOOPS; y++)
{
hr = S_OK;
pRefresher = NULL;
pConfig = NULL;
pEnum = NULL;
pNameSpace = NULL;
pWbemLocator = NULL;
pUnkServ = NULL;
pAuthIdentity = NULL;
bstrNameSpace = NULL;
bstrUserName = NULL;
userbstr = NULL;
domainbstr = NULL;
bstrPassword = NULL;
lID = 0;
lVirtualBytesHandle = 0;
lIDProcessHandle = 0;
dwVirtualBytes = 0;
dwProcessId = 0;
dwNumObjects = 0;
dwNumReturned = 0;
dwIDProcess = 0;
i=0;
if (FAILED (hr = CoInitializeEx(NULL,COINIT_MULTITHREADED)))
{
goto CLEANUP;
}
if (FAILED (hr = CoCreateInstance(
CLSID_WbemLocator,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator,
(void**) &pWbemLocator)))
{
goto CLEANUP;
}
// Connect to the desired namespace.
bstrNameSpace = SysAllocString(NAME_SPACE);
if (NULL == bstrNameSpace)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
userbstr = SysAllocString(USER);
if (NULL == userbstr)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
domainbstr = SysAllocString(DOMAIN);
if (NULL == domainbstr)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
bstrUserName = SysAllocString(FULL_USER);
if (NULL == bstrUserName)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
bstrPassword = SysAllocString(PASSWORD);
if (NULL == bstrPassword)
{
hr = E_OUTOFMEMORY;
goto CLEANUP;
}
if (FAILED (hr = pWbemLocator->ConnectServer(
bstrNameSpace,
bstrUserName, // User name
bstrPassword, // Password
NULL, // Locale
0L, // Security flags
NULL, // Authority
NULL, // Wbem context
&pNameSpace)))
{
goto CLEANUP;
}
pWbemLocator->Release();
pWbemLocator=NULL;
SysFreeString(bstrNameSpace);
bstrNameSpace = NULL;
SysFreeString(bstrUserName);
bstrUserName = NULL;
pAuthIdentity = new SEC_WINNT_AUTH_IDENTITY_W;
SecureZeroMemory(pAuthIdentity, sizeof(*pAuthIdentity));
pAuthIdentity->User = new WCHAR[100];
wcscpy (pAuthIdentity->User , userbstr);
pAuthIdentity->UserLength = wcslen(pAuthIdentity->User);
SysFreeString(userbstr);
userbstr = NULL;
pAuthIdentity->Domain = new WCHAR[100];
wcscpy(pAuthIdentity->Domain, domainbstr);
pAuthIdentity->DomainLength = wcslen(pAuthIdentity->Domain);
SysFreeString(domainbstr);
domainbstr = NULL;
pAuthIdentity->Password = new WCHAR[wcslen(bstrPassword)+1];;
wcscpy(pAuthIdentity->Password, bstrPassword);
pAuthIdentity->PasswordLength = wcslen(pAuthIdentity->Password);
SysFreeString(bstrPassword);
bstrPassword = NULL;
pAuthIdentity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
if (FAILED (hr = CoSetProxyBlanket(pNameSpace,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
pAuthIdentity,
EOAC_NONE)))
{
goto CLEANUP;
}
if (FAILED (hr = pNameSpace->QueryInterface(IID_IUnknown, (void**)
&pUnkServ)))
{
goto CLEANUP;
}
if (FAILED (hr = CoSetProxyBlanket(pUnkServ,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_PKT,
RPC_C_IMP_LEVEL_IMPERSONATE,
pAuthIdentity,
EOAC_NONE)))
{
goto CLEANUP;
}
if (FAILED (hr = CoCreateInstance(
CLSID_WbemRefresher,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWbemRefresher,
(void**) &pRefresher)))
{
goto CLEANUP;
}
if (FAILED (hr = pRefresher->QueryInterface(
IID_IWbemConfigureRefresher,
(void **)&pConfig)))
{
goto CLEANUP;
}
// Add an enumerator to the refresher.
if (FAILED (hr = pConfig->AddEnum(
pNameSpace,
L"Win32_PerfRawData_PerfProc_Process",
0,
NULL,
&pEnum,
&lID)))
{
goto CLEANUP;
}
pConfig->Release();
pConfig = NULL;
//Refresher loop
for(x = 0; x < NUMBER_OF_REFRESHES; x++)
{
if (FAILED (hr =pRefresher->Refresh(0L)))
{
goto CLEANUP;
}
}
// exit loop here
CLEANUP:
if (NULL != bstrNameSpace)
{
SysFreeString(bstrNameSpace);
bstrNameSpace = NULL;
}
if (NULL != bstrUserName)
{
SysFreeString(bstrUserName);
bstrUserName = NULL;
}
if (NULL != userbstr)
{
SysFreeString(userbstr);
userbstr = NULL;
}
if (NULL != domainbstr)
{
SysFreeString(domainbstr);
domainbstr = NULL;
}
if (NULL != bstrPassword)
{
SysFreeString(bstrPassword);
bstrPassword = NULL;
}
if (NULL != pWbemLocator)
{
pWbemLocator->Release();
}
if (NULL != pNameSpace)
{
pNameSpace->Release();
}
if (NULL != pUnkServ)
{
pUnkServ->Release();
}
if (NULL != pAuthIdentity)
{
if (NULL != pAuthIdentity->User)
delete [] pAuthIdentity->User;
pAuthIdentity->User = NULL;
if (NULL != pAuthIdentity->Domain)
delete [] pAuthIdentity->Domain;
pAuthIdentity->Domain = NULL;
if (NULL != pAuthIdentity->Password)
delete [] pAuthIdentity->Password;
pAuthIdentity->Password = NULL;
}
if (NULL != pEnum)
{
pEnum->Release();
}
if (NULL != pConfig)
{
pConfig->Release();
}
if (NULL != pRefresher)
{
pRefresher->Release();
}
CoUninitialize();
if (FAILED (hr))
{
wprintf (L"Error status=%08x\n",hr);
}
}
wprintf (L"End");
Sleep(600000);
return 1;
}
date: Wed, 16 Apr 2008 01:11:06 -0700
author: Tango am
RE: WMI server process leak using refreshers
I'm sorry I don't understand your answer. I understand that you are too busy
to give support to all the possibility faults that may occur in customer's
code; however in this case we are talking about a memory leak in Microsoft's
code, because the problem happens using the example code about using
refreshers, from "Accessing Performance Data in C++"
http://msdn2.microsoft.com/en-us/library/aa384724(VS.85).aspx
In our original post we said we had performed some changes in the original
code, but also that we were able to reproduce the same error without changing
anything in the Microsoft original code (apart from the loop counter)! So, we
are running THE EXAMPLE CODE, changing the number of times the loop is
performed, from 10 to 100000 times.
Running this code to monitor the local computer in a computer running W2003
SP2 has no memory leak, but when running the same executable in a computer
running Windows Vista SP1 or Windows 2008 then the process consumes lot of
memory (in my computer it is consuming 380 MB and it is still growing...).
In all these cases we are monitoring the local computer.
Furthermore, when running the sample code to monitor a remote computer (in
this case we have to modify a little the example to change a setting in the
connection option)and then, when monitoring a remote Windows Vista SP1 and
Windows 2008 computer, the remote WMI process consumes lot of memory (and in
some cases we get a remote "Access Violation" message from the WMI service).
For me, this is clear a bug in WMI or in the Microsoft example code (I think
it is a bug in WMI). This is why I don't understand why this problem is
regarded as "not suitable to be supported in the MSDN newsgroup".
""Jeffrey Tan[MSFT]"" wrote:
> Hi Tango,
>
> Memory leak type of issue is not suitable to be supported in the MSDN
> newsgroup. Microsoft CSS should be best option for this issue.
>
> You can contact Microsoft Product Support directly by contacting us at
> 1-(800)936-5800 or by choosing one of the options listed at:
> http://www.microsoft.com/services/microsoftservices/srv_support.mspx
>
> Thanks for your understanding.
>
> Best regards,
> Jeffrey Tan
> Microsoft Online Community Support
> =========================================
> Delighting our customers is our #1 priority. We welcome your comments and
> suggestions about how we can improve the support we provide to you. Please
> feel free to let my manager know what you think of the level of service
> provided. You can send feedback directly to my manager at:
> msdnmg@microsoft.com.
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
>
>
date: Tue, 22 Apr 2008 07:32:00 -0700
author: Tango am
RE: WMI server process leak using refreshers
Hello Tango,
I am the manager of the Microsoft Managed Newsgroup Support Team, my name
is YanHong. I am reviewing this issue thread and jumping in to share with
you my thought.
Firstly, thanks very much for your feedback on our product. The feedback is
important for us and I checked with Jeffrey. Jeffrey has forwraded the
problem description to our internal discussion alias already.
I think the main point here is that why we recommend you to contact support
service for this type of issue. As Jeffrey pointed out in the link, for
this type of complex issues, we suggest you contact support service so that
one support engineer will work with you directly on it if you need an issue
resolution. In this way, you could get quicker response and talk with our
WMI support engineer directly. Also, according to the problem description,
this might be a product issue. Under this situation, the service request is
free and your MSDN free support incident number won't be deducted.
Thanks very much for your understanding. If there is any unclear, please
feel free to let me know.
Best regards,
Yanhong Huang
Team Manager
Microsoft Online Community Support
date: Wed, 23 Apr 2008 10:57:20 GMT
author: (Yan-Hong Huang[MSFT])
|
|