Hi,

I'm hitting a variety of exceptions on shutdown. Exactly what I hit seems 
to shift as I move things around to try to solve the problem, but here's 
the current one. This doesn't happen 100% of the time, so there must be a 
race involved:

> > avrenderer.exe!aardvark::CServerThread::Run::__l4::<lambda>(kj::Exception 
> && exception) Line 683 C++
>   [External Code] 
>   
> avrenderer.exe!aardvark::CRecoverableExceptionHandler::onRecoverableException(kj::Exception
>  
> && exception) Line 656 C++
>   avrenderer.exe!kj::throwRecoverableException(kj::Exception && 
> exception, unsigned int ignoreCount) Line 878 C++
>   avrenderer.exe!kj::_::Debug::Fault::~Fault() Line 332 C++
>   
> avrenderer.exe!kj::`anonymous-namespace'::AsyncStreamFd::read::__l2::<lambda>(unsigned
>  
> __int64 result) Line 242 C++
>   avrenderer.exe!kj::_::MaybeVoidCaller<unsigned __int64,unsigned 
> __int64>::apply<unsigned __int64 <lambda>(unsigned __int64) 
> >(kj::`anonymous-namespace'::AsyncStreamFd::read::__l2::unsigned __int64 
> <lambda>(unsigned __int64) & func, unsigned __int64 && in) Line 135 C++
>   avrenderer.exe!kj::_::TransformPromiseNode<unsigned __int64,unsigned 
> __int64,unsigned __int64 <lambda>(unsigned 
> __int64),kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue & 
> output) Line 401 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNodeBase::getDepResult(kj::_::ExceptionOrValue
>  
> & output) Line 721 C++
>   avrenderer.exe!kj::_::TransformPromiseNode<kj::_::Void,unsigned 
> __int64,void <lambda>(unsigned 
> __int64),kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue & 
> output) Line 396 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNodeBase::getDepResult(kj::_::ExceptionOrValue
>  
> & output) Line 721 C++
>   avrenderer.exe!kj::_::TransformPromiseNode<bool,kj::_::Void,bool 
> <lambda>(void),kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue 
> & output) Line 396 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNodeBase::getDepResult(kj::_::ExceptionOrValue
>  
> & output) Line 721 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNode<kj::Maybe<kj::Own<capnp::MessageReader>
>  
> >,bool,kj::CaptureByMove<kj::Maybe<kj::Own<capnp::MessageReader> > 
> <lambda>(kj::Own<capnp::MessageReader> &&, bool),kj::Own<capnp::`anonymous 
> namespace'::AsyncMessageReader> 
> >,kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue & output) 
> Line 396 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNodeBase::getDepResult(kj::_::ExceptionOrValue
>  
> & output) Line 721 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNode<kj::Maybe<kj::Own<capnp::IncomingRpcMessage>
>  
> >,kj::Maybe<kj::Own<capnp::MessageReader> 
> >,kj::Maybe<kj::Own<capnp::IncomingRpcMessage> > 
> <lambda>(kj::Maybe<kj::Own<capnp::MessageReader> > 
> &&),kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue & output) 
> Line 396 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNodeBase::getDepResult(kj::_::ExceptionOrValue
>  
> & output) Line 721 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNode<bool,kj::Maybe<kj::Own<capnp::IncomingRpcMessage>
>  
> >,bool <lambda>(kj::Maybe<kj::Own<capnp::IncomingRpcMessage> > 
> &&),kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue & output) 
> Line 396 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   
> avrenderer.exe!kj::_::TransformPromiseNodeBase::getDepResult(kj::_::ExceptionOrValue
>  
> & output) Line 721 C++
>   avrenderer.exe!kj::_::TransformPromiseNode<kj::_::Void,bool,void 
> <lambda>(bool),kj::_::PropagateException>::getImpl(kj::_::ExceptionOrValue 
> & output) Line 396 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get::__l3::<lambda>() 
> Line 703 C++
>   avrenderer.exe!kj::_::RunnableImpl<void <lambda>(void) >::run() Line 303 
> C++
>   avrenderer.exe!kj::_::runCatchingExceptions(kj::_::Runnable & runnable) 
> Line 1023 C++
>   avrenderer.exe!kj::runCatchingExceptions<void <lambda>(void) 
> >(kj::_::TransformPromiseNodeBase::get::__l3::void <lambda>(void) && func) 
> Line 315 C++
>   avrenderer.exe!kj::_::TransformPromiseNodeBase::get(kj::_::ExceptionOrValue 
> & output) Line 703 C++
>   avrenderer.exe!kj::TaskSet::Task::fire() Line 180 C++
>   avrenderer.exe!kj::EventLoop::turn() Line 373 C++
>   avrenderer.exe!kj::WaitScope::poll() Line 413 C++
>   avrenderer.exe!aardvark::CServerThread::Run() Line 689 C++


The specific exception in this case is that AsyncStreamFd wants to read 
some bytes but none are available, presumably because the client has 
disconnected.

The overall flow of the system is something like this:

   1. server starts up
   2. several clients start up. Some are in-process. Some are other 
   processes on the same system.
   3. Run for a while
   4. Clean up all the clients
   5. sleep(1000) <-- this is where the exceptions happen
   6. clean up the server 

The sleep is only there to help me sort out this problem. Once I make 
shutdown deterministic it'll go away. But it appears that clients 
disconnecting and being freed is actually causing an exception on the 
server.

Is there some way for a server to handle client disconnections at arbitrary 
times without throwing? I could just swallow all exceptions as "must be a 
disconnect", but that doesn't seem quite right either since there could 
also be bugs in my own server code causing exceptions. I could make changes 
client-side too, but since clients can always just crash and not tell me 
about it that doesn't fully solve things.

I *am* able to disconnect and reconnect clients while running in general. 
This seems to be unique to shutdown in some way I don't understand. (The 
server doesn't know it's shutting down yet when the exception occurs.)

Any ideas?


Joe

-- 
You received this message because you are subscribed to the Google Groups 
"Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
Visit this group at https://groups.google.com/group/capnproto.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/capnproto/b816998f-a402-4f7f-a7ff-c2ace394f3b7%40googlegroups.com.

Reply via email to