MSXML, deadlock in multithreading application

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hello,
I try to use msxml in multithreading application: one thread read value and another thread write value (I work with different subnodes). But I get a deadlock in application.
I create a simple example for demonstrait it:
<pre class="prettyprint // MSXMLMultithreadingTest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <msxml6.h>
#include <comutil.h>

// Macro that calls a COM method returning HRESULT value.
#define CHK_HR(stmt) do { hr=(stmt); if (FAILED(hr)) goto CleanUp; } while(0)

// Macro to verify memory allcation.
#define CHK_ALLOC(p) do { if (!(p)) { hr = E_OUTOFMEMORY; goto CleanUp; } } while(0)

// Macro that releases a COM object if not NULL.
#define SAFE_RELEASE(p) do { if ((p)) { (p)->Release(); (p) = NULL; } } while(0)

// Helper function to create a VT_BSTR variant from a null terminated string.
HRESULT VariantFromString(PCWSTR wszValue, VARIANT &Variant)
{
HRESULT hr = S_OK;
BSTR bstr = SysAllocString(wszValue);
CHK_ALLOC(bstr);

V_VT(&Variant) = VT_BSTR;
V_BSTR(&Variant) = bstr;

CleanUp:
return hr;
}

DWORD WINAPI SetAttributeThreadFunction( LPVOID lpParam )
{
auto pXMLDom = reinterpret_cast<IXMLDOMDocument *>(lpParam);
BSTR queryString = L"/portfolio";
IXMLDOMNode* tmp;
if( FAILED(pXMLDom->selectSingleNode(queryString, &tmp)) )
{
OutputDebugString(L"FAILED(pXMLDom->selectSingleNode(queryString, &tmp))");
}
IXMLDOMElement* root;
if( FAILED(tmp->QueryInterface(IID_IXMLDOMElement, (void **)&root)) )
{
OutputDebugString(L"FAILED(tmp->QueryInterface(IID_IXMLDOMElement, (void **)&root))");
}
BSTR attrName = L"TestAttribute";
_variant_t value = 10;
while(true)
{
root->setAttribute(attrName, value);
OutputDebugString(L"setAttribute - Okn");
}
}

DWORD WINAPI GetNodeTypedValueThreadFunction( LPVOID lpParam )
{
auto pXMLDom = reinterpret_cast<IXMLDOMDocument *>(lpParam);
BSTR queryString = L"/";
IXMLDOMNode* tmp;
if( FAILED(pXMLDom->selectSingleNode(queryString, &tmp)) )
{
OutputDebugString(L"FAILED(pXMLDom->selectSingleNode(queryString, &tmp))");
}
VARIANT _result;
VariantInit(&_result);

while(true)
{
tmp->get_nodeTypedValue(&_result);
OutputDebugString(L"get_nodeTypedValue - Okn");
}
}

// Helper function to create a DOM instance.
HRESULT CreateAndInitDOM(IXMLDOMDocument **ppDoc)
{
HRESULT hr = CoCreateInstance(__uuidof(FreeThreadedDOMDocument60), NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(ppDoc));
if (SUCCEEDED(hr))
{
// these methods should not fail so dont inspect result
(*ppDoc)->put_async(VARIANT_FALSE);
(*ppDoc)->put_validateOnParse(VARIANT_FALSE);
(*ppDoc)->put_resolveExternals(VARIANT_FALSE);
}
return hr;
}

void loadDOMRaw()
{
HRESULT hr = S_OK;
IXMLDOMDocument *pXMLDom = NULL;
IXMLDOMParseError *pXMLErr = NULL;

BSTR bstrXML = L"<portfolio xmlns:dt="urn:schemas-microsoft-com:datatypes </portfolio>";
BSTR bstrErr = NULL;
VARIANT_BOOL varStatus;
VARIANT varFileName;
VariantInit(&varFileName);

CHK_HR(CreateAndInitDOM(&pXMLDom));

// XML file name to load
CHK_HR(pXMLDom->loadXML(bstrXML, &varStatus));
if (varStatus == VARIANT_TRUE)
{
CHK_HR(pXMLDom->get_xml(&bstrXML));
printf("XML DOM loaded from stocks.xml:n%Sn", bstrXML);
}
else
{
// Failed to load xml, get last parsing error
CHK_HR(pXMLDom->get_parseError(&pXMLErr));
CHK_HR(pXMLErr->get_reason(&bstrErr));
printf("Failed to load DOM from stocks.xml. %Sn", bstrErr);
}
auto handle1 = CreateThread(
NULL, // default security attributes
0, // use default stack size
SetAttributeThreadFunction, // thread function name
pXMLDom, // argument to thread function
0, // use default creation flags
NULL); // returns the thread identifier
auto handle2 = CreateThread(
NULL, // default security attributes
0, // use default stack size
GetNodeTypedValueThreadFunction, // thread function name
pXMLDom, // argument to thread function
0, // use default creation flags
NULL); // returns the thread identifier

Sleep(1000 * 300);

TerminateThread(handle1, 0);
TerminateThread(handle2, 0);

CleanUp:
SAFE_RELEASE(pXMLDom);
SAFE_RELEASE(pXMLErr);
SysFreeString(bstrXML);
SysFreeString(bstrErr);
VariantClear(&varFileName);
}

int _tmain(int argc, _TCHAR* argv[])
{
HRESULT hr = CoInitialize(NULL);
if(SUCCEEDED(hr))
{
loadDOMRaw();
CoUninitialize();
}
return 0;
}
[/code]
<br/>
What I am doing wrong?
<br/>


View the full article
 
Back
Top