Trouble with asio using lib pion and boost.function
Hi there, I'm not actually sure this is a boost problem but I'll give it a try and ask for your opinion. Boost version is 1.36 I have a daemon here realising a web interface using pion and asio. Pion is also using asio. On Linux everything runs fine and I have my web interface, but using the same code on windows / vs 2005 I get the weirdest errors such as " Unhandled exception at 0x1004e55d in myapp.exe: 0xC0000005: Access violation reading location 0xcdcdcdd1." The debugger tells me this happens in function_template.hpp: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> typename BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> ::operator()(BOOST_FUNCTION_PARMS) const { if (this->empty()) boost::throw_exception(bad_function_call()); return static_cast<vtable_type*>(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); } #endif It says the static_cast rises the exception (?!) Damn MS. Anyway, I debugged into it and the last thing the debugger stepped into was in asio: size_t run(boost::system::error_code& ec) { if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0) { ec = boost::system::error_code(); return 0; } call_stack<win_iocp_io_service>::context ctx(this); size_t n = 0; while (do_one(true, ec)) if (n != (std::numeric_limits<size_t>::max)()) ++n; return n; } I don't know which line though. Can anyone help shed some light on this? Thanks and greetings... Stephan
AMDG Stephan Menzel wrote:
I'm not actually sure this is a boost problem but I'll give it a try and ask for your opinion. Boost version is 1.36
I have a daemon here realising a web interface using pion and asio. Pion is also using asio. On Linux everything runs fine and I have my web interface, but using the same code on windows / vs 2005 I get the weirdest errors such as
" Unhandled exception at 0x1004e55d in myapp.exe: 0xC0000005: Access violation reading location 0xcdcdcdd1."
The debugger tells me this happens in function_template.hpp:
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> typename BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> ::operator()(BOOST_FUNCTION_PARMS) const { if (this->empty()) boost::throw_exception(bad_function_call());
return static_cast<vtable_type*>(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); } #endif
It says the static_cast rises the exception (?!) Damn MS.
a) Is the error on the static_cast or on reading the function pointer? b) does it happen consistently?
Can anyone help shed some light on this?
This could be the 1.36 Boost.Function thread safety regression. There is a race condition that can prevent invoker from being properly initialized before it is used. In Christ, Steven Watanabe
Hi Steven,
return static_cast<vtable_type*>(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); } #endif
It says the static_cast rises the exception (?!) Damn MS.
a) Is the error on the static_cast or on reading the function pointer?
Alas, I can't really tell. For the compiler this is one line. But I have to assume it's coming out of the functor. At least this is what the debug run looked like.
b) does it happen consistently?
Yes, every time.
This could be the 1.36 Boost.Function thread safety regression. There is a race condition that can prevent invoker from being properly initialized before it is used.
Bad news indeed. But it would have to be something rather platform dependent such as this. Despite all efforts I couldn't reproduce it on either 64bit or 32bit GNU/Linux boxes I tried. Alas, it still get's worse. Trying to figure out if an update to 1.37 would be in place I ran into this: http://groups.google.tl/group/boost-list/browse_thread/thread/c19823879d3cde... Apparently boost.asio fails to work in 1.37 on windows. Which is mighty disappointing, since I hold asio in such high esteem. So is there any other way of fixing that so I could see if that was it? A patch for 1.36 perhaps? Apart from this, wouldn't a race condition bound to be a little more hard to catch? Usually the buggers tend to be rather unreproducable to the point you doubt they exist. Cazart, Stephan
AMDG Stephan Menzel wrote:
return static_cast<vtable_type*>(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); } #endif
It says the static_cast rises the exception (?!) Damn MS.
a) Is the error on the static_cast or on reading the function pointer?
Alas, I can't really tell. For the compiler this is one line. But I have to assume it's coming out of the functor. At least this is what the debug run looked like.
You could look at the disassembly... However, in the light of the following, it seem more likely that the "this" pointer is invalid.
b) does it happen consistently?
Yes, every time.
Apart from this, wouldn't a race condition bound to be a little more hard to catch? Usually the buggers tend to be rather unreproducable to the point you doubt they exist.
Yeah. That doesn't sound like a race condition, then. The particular race involved has a very small critical section. In Christ, Steven Watanabe
Hi Steven
return static_cast<vtable_type*>(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); }
a) Is the error on the static_cast or on reading the function pointer?
You could look at the disassembly...
Good call! Neat feature, this Visual stuff has got here. I see lots of things along those lines. I try to boil it down to a more interesting part: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> typename BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> ::operator()(BOOST_FUNCTION_PARMS) const { 1004E4B0 push ebp 1004E4B1 mov ebp,esp 1004E4B3 push 0FFFFFFFFh 1004E4B5 push offset __ehhandler$??R?$function1@XV?$shared_ptr@VTCPConnection@net@pion@@@boost@@@boost@@QBEXV?$shared_ptr@VTCPConnection@net@pion@@@1@@Z (1005A600h) 1004E4BA mov eax,dword ptr fs:[00000000h] 1004E4C0 push eax 1004E4C1 sub esp,40h 1004E4C4 push edi 1004E4C5 push ecx 1004E4C6 lea edi,[ebp-4Ch] 1004E4C9 mov ecx,10h 1004E4CE mov eax,0CCCCCCCCh 1004E4D3 rep stos dword ptr es:[edi] 1004E4D5 pop ecx 1004E4D6 mov eax,dword ptr [___security_cookie (1007C920h)] 1004E4DB xor eax,ebp 1004E4DD push eax 1004E4DE lea eax,[ebp-0Ch] 1004E4E1 mov dword ptr fs:[00000000h],eax 1004E4E7 mov dword ptr [ebp-10h],ecx 1004E4EA mov dword ptr [ebp-4],0 if (this->empty()) 1004E4F1 mov ecx,dword ptr [ebp-10h] 1004E4F4 call boost::function_base::empty (100033B4h) 1004E4F9 movzx eax,al 1004E4FC test eax,eax 1004E4FE je boost::function1<void,boost::shared_ptr<pion::net::TCPConnection> >::operator()+7Dh (1004E52Dh) boost::throw_exception(bad_function_call()); 1004E500 lea ecx,[ebp-3Ch] 1004E503 call boost::bad_function_call::bad_function_call (100015B9h) 1004E508 mov dword ptr [ebp-44h],eax 1004E50B mov ecx,dword ptr [ebp-44h] 1004E50E mov dword ptr [ebp-48h],ecx 1004E511 mov byte ptr [ebp-4],1 1004E515 mov edx,dword ptr [ebp-48h] 1004E518 push edx 1004E519 call boost::throw_exception<boost::bad_function_call> (100024FAh) 1004E51E add esp,4 1004E521 mov byte ptr [ebp-4],0 1004E525 lea ecx,[ebp-3Ch] 1004E528 call boost::bad_function_call::~bad_function_call (10002199h) return static_cast<vtable_type*>(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); 1004E52D sub esp,8 1004E530 mov ecx,esp 1004E532 mov dword ptr [ebp-40h],esp 1004E535 lea eax,[ebp+8] 1004E538 push eax 1004E539 call boost::shared_ptr<pion::net::TCPConnection>::shared_ptr<pion::net::TCPConnection> (10003003h) 1004E53E mov dword ptr [ebp-4Ch],eax 1004E541 mov ecx,dword ptr [ebp-10h] 1004E544 add ecx,8 1004E547 push ecx 1004E548 mov edx,dword ptr [ebp-10h] 1004E54B mov eax,dword ptr [edx] 1004E54D mov ecx,dword ptr [eax+4] 1004E550 call ecx and so on and so forth and suchlike.
However, in the light of the following, it seem more likely that the "this" pointer is invalid.
Indeed. There's even a if (this->empty()) boost::throw_exception(bad_function_call()); to be seen. What I see is either this exception or it is a crash trying to access this. In any case, it's platform specific. But I still don't know how to proceed. Wouldn't here be a bug report in order? Cazart, Stephan
participants (2)
-
Stephan Menzel
-
Steven Watanabe