MSXML, deadlock in multithreading application
-
2012년 2월 15일 수요일 오전 3:13
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:
// 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 - Ok\n"); } } 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 - Ok\n"); } } // 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 don't 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%S\n", 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. %S\n", 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; }
What I am doing wrong?
모든 응답
-
2012년 2월 16일 목요일 오전 6:07중재자
Hi Evgeniy Mironov,
Welcome!
We will do some more pending research about your problem and come back as soon as possible, Thanks for understanding.
Have a nice day.
Alan Chen[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

-
2012년 2월 22일 수요일 오후 5:21
Hi Evgeniy,
While I would like to help you this particular question falls into the paid support category which requires a more in-depth level of support. Please visit the below link to see the various paid support options that are available to better meet your needs. http://support.microsoft.com/default.aspx?id=fh;en-us;offerprophone
Provide the sample code and the xml files it is parsing. We would try to create a repro at our end and find the cause of the multi-threading issue with the resolution.
Regards,
Angshuman Nayak

