I found the problem and it has nothing to do with any of this. The problem, as quite rightly pointed out by weijin is that when the closed flag by one thread, another thread can delete the NetVC. This is expected and desirable, however, unfortunately do_io_close() is accessing the "nh" variable (which happens to be in the NetVC), and it is dereferencing it to get the mutex to check to see if it is running in the same thread as the NetVC and it is doing so after the closed flag is set.
The simple solution is to move the read of nh->mutex->thread_holding above the setting of "closed". Please see patch TS-857-jp1.patch attached to TS-857. On Sat, Mar 24, 2012 at 11:32 AM, Alan M. Carroll < a...@network-geographics.com> wrote: > > I will try to be more explicit. Consider my timeline once again and the > callsite in thread A where do_io_close is called. Assume that thread B is > not attempting to access the transaction (there is no contention for the > netVC or the transaction lock). At that point - Out of the box ATS runs a transaction only on one thread, so thread A is the only thread in play. I added an assert and confirmed this. Are you running a custom configuration? > 1) What ATS data structure chain can be used to detect that there exists > an instance of HttpServerSession in thread B with member server_vc pointing > at this netVC, so that thread A knows a reference needs to be dropped, or > it should wait for thread B to drop the reference? > If thread A is calling do_io_close() then it is holding the transaction lock. If it holds that lock, then it can access all of the data structures of the transaction, including all copies of the NetVC pointer (save the one held in the NetProcessor which will not result in calls into the transaction and will be cleared once the "closed" flag is set in do_io_close()). In fact, to call do_io_close, thread A must be holding the single copy of the NetVC pointer in the transaction, and indeed must be holding the very HttpServerSession and so would do: VConnection *temp_vc = m_net_vc; *m_net_vc = NULL; temp_vc->do_io_close(); > > Presuming the intent is to do as you describe, drop all references - > > 2) What ATS data structure chain can be used to access that > HttpServerSession::server_vc so that all references can be dropped? > see above > > 3) What lock should be acquired to prevent simultaneous access to the > HttpServerSession by thread A and thread B when thread A drops the > reference in HttpServerSession::server_vc? > the transaction lock > > 3A) If this is the transaction lock, how is the circularity avoided where > to access server_vc safely you need to acquire the lock, and to acquire the > lock you need to access server_vc? > the lock is taken out automatically by all callback to the transaction. The lock is created when the connection is accepted. It is the passed to each processor so that when the processor calls back with an event it *must* take the lock out before calling into the transaction. Therefore, if you are running in the transaction, you have the lock. > > 4) What mechanism (present or future) exists to enable thread B to notice > that HttpServerSession::server_vc has been modified to drop the reference? > > Nobody "modifies" HttpServerSession::server_vc save the transaction itself. At which time it should drop the reference.