Q. where is client session created? A. in etch_transport.tcpxfact_session_accepted(), called from etch_tcpsvr_acceptproc(), then new_etch_session() the delivery service is populated there, the remote client, server impl, and stub are populated in new_helper_accepted_server(), which instantiates them. Q. where is client session blocking receive loop? A. etch_tcpserver.etch_tcpserver_listenerproc() Q. where is delivery service created? A. etch_transport.tcpxfact_session_accepted, and then etch_transport.new_etch_transport(), and then etch_transport.new_tcp_delivery_service() Q. where is delivery service torn down? (prior to code mods for session support) A. etch_transport.destroy_etch_listener(). this is the destructor for the main listener instantiated in [main]. obviously it is wrong to destroy the delivery service there, as well as remote client and stub. Q. where should delivery service be torn down now? A. etch_tcpserver_listenerproc() exit, then transport.destroy_etch_clientsession() a. actual teardown must be in code that can see transport.h. and has an i_sessionlistener* reference. b. end of session state is first known in etch_tcpserver.etch_tcpserver_listenerproc(), when the receive loop exits. this returns to etch_apr_threadproc. Q. where is threadproc etch_tcpserver_listenerproc() started from? A. etch_tcpserver.etch_tcpsvr_acceptproc(). this method calls back into transport via tcpserver->on_session_accepted(), which is etch_transport.tcpxfact_session_accepted(). THIS METHOD COULD RETURN AN OBJMASK SESSION OBJECT c. ideally teardown would be on main thread, however we don't have an easy way to do that, since the thread exit return is generic. d. we'll try calling the session object destructor at exit of etch_tcpserver.etch_tcpserver_listenerproc(). a. the connection cx.session is an objmask* reference to the etch_session* object.