When things to more than you think
-
I just spent nearly two days debugging an COM exe server using ATL and boost. There is a boost thread, acting as an asynchronous task manager that gets task queued which do callbacks into COM objects (into JScript objects). The thread was hanging in
join()
, even though a breakpoint set at the end of the thread function was hit. The code was written by a collegue, who is a god with boost, but rather new to ATL - and he hates it. Me in turn did not use a lot of boost (yet), but with COM/ATL I have quite some experience, and I like it. So first I suspected boost to be somehow buggy, although I could not really imagine that such a widely used thing likeboost::thread
would have such a serious bug or a somehow screwed functionality. Here is (shortened) how the thread looks:void operator()()
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
BOOST_SCOPE_EXIT_ALL(&) { CoUninitialize(); };
try {
// lots of code here...
// e.g. running a task from a task queue calling back into javascript
// and creating a few js-objects...
// and more...
// and more...
} catch (boost::thread_interrupted &) {
ATLTRACE(L"Thread interrupted\n");
}
}As I said: A breakpoint set at the last closing curly brace got hit, but the
join()
call from the main thread that triggered the thread interruption never finished. After a while (quite a while!) of playing around, debugging (a release version btw, since the problem happened only in a release build) and staring at the code I noticed the neat little line near the top of the thread:BOOST_SCOPE_EXIT_ALL(&) { CoUninitialize(); };
"Wait a sec! What's that?" "
BOOST_SCOPE_EXIT_ALL
- Maybe this means, it executes some code when the current scope exits? MaybeCoUninitialize()
?. And doesn'tCoUninitialize()
block, when the current thread still holds some COM object references?" So I started to dig into the code of the actual tasks that were executed here, and one of them in deed creates some objects. But since my colleague learned COM from me and I slap his fingers everytime I see a raw pointer somewhere, and also from what I found in the code there should not be a problem. The object was created nicely viaCComPtr<IDispatch> createJSObjectInstance()
{
CComPtr<IDispatchEx> creatorObject = threadMarshaller->get();
DISPPARAMS params = {0};
_variant_t result; -
I just spent nearly two days debugging an COM exe server using ATL and boost. There is a boost thread, acting as an asynchronous task manager that gets task queued which do callbacks into COM objects (into JScript objects). The thread was hanging in
join()
, even though a breakpoint set at the end of the thread function was hit. The code was written by a collegue, who is a god with boost, but rather new to ATL - and he hates it. Me in turn did not use a lot of boost (yet), but with COM/ATL I have quite some experience, and I like it. So first I suspected boost to be somehow buggy, although I could not really imagine that such a widely used thing likeboost::thread
would have such a serious bug or a somehow screwed functionality. Here is (shortened) how the thread looks:void operator()()
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
BOOST_SCOPE_EXIT_ALL(&) { CoUninitialize(); };
try {
// lots of code here...
// e.g. running a task from a task queue calling back into javascript
// and creating a few js-objects...
// and more...
// and more...
} catch (boost::thread_interrupted &) {
ATLTRACE(L"Thread interrupted\n");
}
}As I said: A breakpoint set at the last closing curly brace got hit, but the
join()
call from the main thread that triggered the thread interruption never finished. After a while (quite a while!) of playing around, debugging (a release version btw, since the problem happened only in a release build) and staring at the code I noticed the neat little line near the top of the thread:BOOST_SCOPE_EXIT_ALL(&) { CoUninitialize(); };
"Wait a sec! What's that?" "
BOOST_SCOPE_EXIT_ALL
- Maybe this means, it executes some code when the current scope exits? MaybeCoUninitialize()
?. And doesn'tCoUninitialize()
block, when the current thread still holds some COM object references?" So I started to dig into the code of the actual tasks that were executed here, and one of them in deed creates some objects. But since my colleague learned COM from me and I slap his fingers everytime I see a raw pointer somewhere, and also from what I found in the code there should not be a problem. The object was created nicely viaCComPtr<IDispatch> createJSObjectInstance()
{
CComPtr<IDispatchEx> creatorObject = threadMarshaller->get();
DISPPARAMS params = {0};
_variant_t result;Interesting!! :)
My programming get away... The Blog... DirectX for WinRT/C# since 2013! Taking over the world since 1371!