mono/mono — pull request #234 by kripper (2012-03-04 00:47:36+00:00)
Title: Fixes Bug #333898 / Fixes Bug of losing ASP.NET sessions (InProcSessions) when using Phalanger with Mono

For previous comments, se here: https://github.com/mono/mono/pull/229

---

Ok. I identified and fixed the bug:

- The first request calls OnReleaseRequestState() for acquiring a exclusive lock on the Session store.
- Next concurrent requests trying to access the same Session store will wait in WaitForStoreUnlock()
- WaitForStoreUnlock() calls StoreUnlockWaitCallback() for checking if the Session store was released
- This is done by calling SessionStateModule::GetStoreData(), which changes the shared SessionStateModule::storeData variable.
- If the storeData is locked (it was locked by the first request), a NULL value is returned and stored in storeData.
- When the first request is released on OnReleaseRequestState(), storeData is NULL and GetItemExclusive() is called with a item == null, so the session is destroyed (as reported in bug #333898)

To fix this bug, I changed SessionStateModule::GetStoreData() so it doesn't assign a NULL value to storeData when an item is locked.
SessionStateModule::GetStoreData() will now return a SessionStateStoreData object, which will be assigned in StoreUnlockWaitCallback() only when not NULL:

void StoreUnlockWaitCallback (object s) {
CallbackState state = (CallbackState) s;

SessionStateStoreData item = GetStoreData (state.Context, state.SessionId, state.IsReadOnly);

if (item == null && storeLocked && (storeLockAge > executionTimeout)) {
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": " + "TimedOut!!!");
handler.ReleaseItemExclusive (state.Context, state.SessionId, storeLockId);
storeData = null; // Create new state
state.AutoEvent.Set ();
}
else if (item != null && !storeLocked) {
storeData = item;
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ": " + "Store was unlocked -> Despertar waiting thread.");
state.AutoEvent.Set ();
}
}

So, if the store was locked (that's mostly the case because we are waiting it to unlock), storeData will not be changed for the executing request (which got the lock) and also will not the destroy the session during OnReleaseRequestState().