Bug #62266 Timed out sessions are removed without notification
Submitted: 26 Aug 2011 13:43 Modified: 27 Jul 2012 23:24
Reporter: David Newcomb (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:Connector / NET Severity:S3 (Non-critical)
Version:6.5.4 OS:Any
Assigned to: Gabriela Martinez Sanchez CPU Architecture:Any
Tags: Contribution

[26 Aug 2011 13:43] David Newcomb
Description:
The IntervalMinutes column inside the table my_aspnet_sessioncleanup defines how often the session-expiry scanner runs. This thread goes through the database and deletes any entry that is sessionState.timeout (from web.config) minutes old.

The session holds finite resources that must be returned to the system. When the session-expiry scanner deletes a session entry the application is not notified and so can't free these resources.

There's no way to switch off the session-expiry scanner or the session timeout mechanism (see bug #62195). We as application developers, will all have to write an extra thread that runs before yours and tidys up those resources and then the session data held in the database as you can't do one without the other.

The Session-State Store Provider documentation ( http://msdn.microsoft.com/en-us/library/ms178587.aspx - Deleting Expired Session-Store Data
 para 2) specifies that:
"If your data source can be configured to delete expired session data according to the session Timeout property, you can use the SetItemExpireCallback method to reference the delegate for the Session_OnEnd event and raise it when deleting expired session data."

So there are 3 choices:
1) Ignore sessionstate.timeout and don't delete the session data held in the database.
2) Keep the sessionstate.timeout and implement the SetItemExpireCallback to notify the SessionProvider to call Session_End.
3) Add an configuration option do the callback or not; some users may not want the extra overhead as they don't have resources that need freeing.

To help you make the right choice ;) I have implemented all of this and I attach the code for you! Everything fits into SessionProvider.cs

How to repeat:
Set up driver as sessionState provider.
Create a web page that saves something in the session.
Wait for timeout to happen.
Entry is deleted from the database but Global(.asax).Session_End is not called.

Suggested fix:
Recompile driver using my SessionProvider.cs.
Add enableSessionExpireCallback=true to the provider.
Implement Global(.asax).Session_End
[26 Aug 2011 14:29] David Newcomb
SessionProvider.cs

Attachment: SessionProvider.cs.zip (unknown/unknown, text), 7.03 KiB.

[27 Sep 2011 14:55] Gabriela Martinez Sanchez
Tested with the CLR 4, 6.4.3 Connector and VS 2010 with SP1, but unable to reproduce it. Could you please provide CLR version, VS and mysqlclient.data.dll if possible.
[27 Sep 2011 15:33] David Newcomb
Are you sure your comment was meant for this bug? Did you mean to add this comment to Bug #62176 instead? This is the bug relating to removing sessions without notification and not VS plugin.
[27 Sep 2011 15:53] David Newcomb
Sorry, I was getting confused - I think!

In file: mysql-connector-net-6.4.[4|3]-src\Source\MySql.Web\SessionProvider.cs the function SetItemExpireCallback(SessionStateItemExpireCallback expireCallback) returns false and the expireCallback is not recorded for later.

When the TimerCallback expires and calls CleanupOldSessions() the session is deleted from the database but expireCallback is not called (because it was never saved earlier). The main program is never notified that the expired session has been removed from the database.

From the code, I don't understand how you would think it is working? There is no code to implement the callback which ultimately calls Global.Session_End and gives the application writer the opportunity to clean away any resources held in the session.
[28 Sep 2011 19:57] Gabriela Martinez Sanchez
After reviewing it, this definitely falls into a feature request. We'll consider including it possibly in 6.5. Please note that we cannot use your contribution without getting you to sign a code contribution agreement.
[29 Sep 2011 8:17] David Newcomb
Without this feature I (we all) would need to write an extra bit of code to identify expired sessions and clean up the resources associated with them. There is an argument for not deleting sessions if you can't provide the callback but the specification leaves this decision up to the driver developer. It is complicated by the fact that I can't switch off the timer that deletes the expired sessions (Bug #62195).

I don't mind you using my code but as this is an open source project my code comes AS IS and without warranty, for any use by anyone, etc. Where/What do I have to sign?
[24 Jan 2012 11:18] David Newcomb
Where are we on this? I understand that you have my source code, so can you give me an ETA?
[5 Jun 2012 17:00] Gabriela Martinez Sanchez
The fix and code contribution for this bug has been pushed and is available in the following versions: 6.4.5 which is already released (http://www.mysql.com/downloads/) and for future releases in version 6.5.5 and 6.6.x.
[10 Jul 2012 13:27] David Newcomb
I have downloaded the source for 6.5.4 and done a diff on SessionProvider.cs (between 6.4.3 and 6.5.4).
The only change is that you have renamed the tables my_aspnet_SessionCleanup to my_aspnet_sessioncleanup and my_aspnet_Sessions to my_aspnet_sessions.

The session clean up mechanism for 6.4.3 and 6.5.4 are exactly the same. Am I missing something? Where is it different?
cleanupTimer is still being set to run every minute and there is no way to switch it off.
CleanupOldSessions() still deletes sessions without informing anyone. How is it fixed?
[11 Jul 2012 8:56] Tonci Grgin
David, I am sorry but you used wrong version to test (6.5.4). Gaby said "...and for future releases in version 6.5.5 and 6.6.x.".
Could you please grab 6.5.5 when available and report back your findings to us?
[11 Jul 2012 9:08] David Newcomb
Yes but he all so mentioned that the fix had been pushed into 6.5.4 which has already been release.

 "The fix and code contribution for this bug has been pushed and is available in the following versions: 6.4.5 which is already released..."

Prehaps to avoid any ambiguity next time don't mention the release it's not in and only mention the release it is in. I will report back with confirmation.
[12 Jul 2012 7:51] Tonci Grgin
David, check again, 6.4.5 (yes) and 6.5.4 (which you tested, no) but point taken :)
Now, since we claim to support API, we have to fully comply to it:
http://dev.mysql.com/doc/refman/5.5/en/connector-net-programming-asp-provider.html
"MySQL Connector/Net provides support for the ASP.NET 2.0 provider model."

In this case, we did not, so it can not be treated as S4 but, at least, S3.

Thanks for catching this and for providing us with patch.
[27 Jul 2012 23:24] John Russell
Added to changelog for 6.4.5, 6.5.5: 

Formerly, cleanup operations for expired sessions were fully
automatic, with no ability to catch the timeout event and do
application-specific cleanup. This fix adds a
enableSessionExpireCallback connection option to let developers catch
the event when a session expires. When enableSessionExpireCallback is
enabled, the global.asax.session_end event is raised before data is
deleted from the my_aspnet_sessions table. When
enableSessionExpireCallback is disabled, the data is deleted from the
my_aspnet_sessions table without raising the event first. The timeout
period for session expiry is specified in the web.config file, in the
timeout option of the sessionState section.