Skip to content

Commit 537c645

Browse files
committed
doc: Improve ProxyServerCustom class documentation
Add note about cleaning up custom state asynchronously, after a recently fixed bug where there was a wallet deadlock when the node connection was broken, caused by the ProxyServerCustom<WalletLoader> destructor trying to delete the wallet CScheduler object synchronously (on the IPC EventLoop thread) while a scheduled task was trying to make an Chain isReadyToBroadcast() IPC call.
1 parent d4d9f93 commit 537c645

File tree

1 file changed

+20
-2
lines changed

1 file changed

+20
-2
lines changed

include/mp/proxy.h

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,26 @@ struct ProxyServerBase : public virtual Interface_::Server
136136
ProxyContext m_context;
137137
};
138138

139-
//! Customizable (through template specialization) base class used in generated ProxyServer implementations from
140-
//! proxy-codegen.cpp.
139+
//! Customizable (through template specialization) base class which ProxyServer
140+
//! classes produced by generated code will inherit from. The default
141+
//! specialization of this class just inherits from ProxyServerBase, but custom
142+
//! specializations can be defined to control ProxyServer behavior.
143+
//!
144+
//! Specifically, it can be useful to specialize this class to add additional
145+
//! state to ProxyServer classes, for example to cache state between IPC calls.
146+
//! If this is done, however, care should be taken to ensure that the extra
147+
//! state can be destroyed without blocking, because ProxyServer destructors are
148+
//! called from the EventLoop thread, and if they block, it could deadlock the
149+
//! program. One way to do avoid blocking is to clean up the state by pushing
150+
//! cleanup callbacks to the m_context.cleanup list, which run after the server
151+
//! m_impl object is destroyed on the same thread destroying it (which will
152+
//! either be an IPC worker thread if the ProxyServer is being explicitly
153+
//! destroyed by a client calling a destroy() method with a Context argument and
154+
//! Context.thread value set, or the temporary EventLoop::m_async_thread used to
155+
//! run destructors without blocking the event loop when no-longer used server
156+
//! objects are garbage collected by Cap'n Proto.) Alternately, if cleanup needs
157+
//! to run before m_impl is destroyed, the specialization can override
158+
//! invokeDestroy and destructor methods to do that.
141159
template <typename Interface, typename Impl>
142160
struct ProxyServerCustom : public ProxyServerBase<Interface, Impl>
143161
{

0 commit comments

Comments
 (0)