[ASP.NET] Random 'not available in this context' errors

Pagina: 1
Acties:

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Topicstarter
Sinds enige tijd heb ik een wederkerend probleem in een ASP.NET v1.1 applicatie framework dat ik heb geschreven. De applicaties werken perfect, alles doet het naar behoren en iedereen is happy, totdat op een gegeven moment de chaostheorie inslaat gewoon terwijl iemand een pagina opvraagt. Op dat moment is de applicatie permanent borked totdat aspnet_wp.exe wordt afgeschoten of IIS zelf overnieuw opgestart wordt.

Dus wat is het probleem? Laten we eerst even kijken naar de korte samenvatting van de originele code. M'n framework biedt zelf een class die afleidt van System.Web.HttpApplication, en waar uiteindelijke applicaties hun Global class weer van afleiden. Van de 'tussenclass' heb ik de Init() overloaded:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public override void Init()
{
    SessionStateModule module;
    
    // Invoke base implementation first
    base.Init();
    
    // Register event handlers
    module              = (SessionStateModule)Modules["Session"];           
    module.Start        += new EventHandler(Application_SessionStart);
    AcquireRequestState += new EventHandler(Application_AcquireRequestState);
    Error               += new EventHandler(Application_Error); 

    ...
}

Hierin plaats ik dus 3 belangrijke events op application startup, waarvan de Session_Start event het belangrijkste is: net zoals ik in de HttpApplication tussenclass veel framework-related informatie opsla, heb ik voor iedere session ook een 'schaduwobject' waarin ik eenmalig securitysettings van een centrale server ophaal en deze voor de sessieduratie laat bestaan. Enige relevante code uit dit event:
C#:
1
2
// Create new session variable (no need to store, it'll be done static)
new WebSession(securityManager.CreateSession(User.Identity.Name));

De CreateSession boeit niet echt, de constructor van WebSession wel:
C#:
1
2
3
4
5
6
7
8
9
internal WebSession(SecuritySession securitySession)
{
    Application app         = Application.Instance;
            
    // Set static reference
    app.Session[sessionVariableName] = this;

    ...
}

Instance is simpelweg de singleton-accessor van m'n tussenclass die het correcte type retourneert, en SessionVariableName is een constant string. En hier gaat het dus fout: waar deze code continu perfect werkt, gaat het ooit, binnen 1 uur tot 14 dagen bij stevig gebruik, in een toestand komen waar iedere nieuwe sessie permanent kapotknalt op de "app.Session"-regel hierboven met "Session State not available in this context". Dit is sowieso al onzin, omdat zelfs de callstack op dat moment helder aangeeft dat de event uit de SessionStateHandler komt en Session dus wel degelijk beschikbaar is (zie ook bijv. deze tutorial die exact hetzelfde doet).

In ieder geval gingen we het probleem onderzoeken. Eerst heb ik een workaround geprobeerd die heel de afhankelijkheid van SessionState dropte. Dit was een hoop creatieve code die op basis van Request.Cookies en HttpApplication.Cache simpelweg het effect van Sessions emuleerde. Werkte perfect, totdat binnen X tijd ineens de applicatie borked was en iedere nieuwe sessie permanent kapotknalt met "Request not available in this context" zodra ik de cookies uitlees.

Intussen heel Internet en de Knowledge Base uitgegraven, maar niemand leek een vergelijkbaar probleem te hebben. Sterker nog, Internet staat vol met voorbeelden waarin mensen in Session_Start events de Request en Session objecten aanspreken, wat hier dus absoluut niet wil. Wel vond ik een hoop referenties dat men het ook in AcquireRequestState event deed. Dus heb ik dat ook geprobeerd... ik heb alle SessionStart code 'genuked' en het verplaatst naar het event wat ik al had:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
private void Application_AcquireRequestState(object sender, EventArgs e)
{
    ...

    // Is this the first request of a session?
    if(Session.IsNewSession)
    {
        // Create new session variable (no need to store, it'll be done static)
        new WebSession(securityManager.CreateSession(User.Identity.Name));          
    }
    ...
}

Helaas bleek deze code nog instabieler, nu gaat het ding binnen ~15 minuten intensief gebruik per definitie op z'n gat, deze keer met "Session State is not available in this context" doodleuk binnen de callstack van de AcquireRequestState event.

De vraag dus: kent iemand dit gedrag? Weet iemand een oorzaak/workaround? Maak ik vreemde aannames die niet zouden mogen? Kijk ik wellicht over een multithreading/synchronization issue heen?

Professionele website nodig?


  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

Zou de oorzaak kunnen liggen in het feit dat sessies op harde schijf of geheugen worden opgeslagen? Het lijkt me sterk dat dit intended behaviour is namelijk; en het probleem zou ik dan ook zoeken in de ASP engine, het OS of de hardware :) Heb je het probleem op een andere machine kunnen herproduceren?

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


Verwijderd

Singleton + onvoorspelbare errors is meestal een threading probleem...

Hoe heb je de singleton geimplementeerd? Heb je geprobeerd het problematische stuk code met een lock() statement te omringen?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Topicstarter
Verwijderd schreef op donderdag 28 april 2005 @ 19:26:
Singleton + onvoorspelbare errors is meestal een threading probleem...

Hoe heb je de singleton geimplementeerd? Heb je geprobeerd het problematische stuk code met een lock() statement te omringen?
Je hebt vrijwel zeker gelijk :)

Ik zat het ook al in deze hoek te zoeken, maar kon me er weinig bij voorstellen omdat de bug schijnbaar even consequent op QA als op productieservers optrad, en de QA-server krijgt echt nondeju weinig traffic, laat staan concurrent requests. Daarnaast wordt de application singleton 1 keer per applicatie geschreven, first request logischerwijs, en vanaf dat moment enkel uitgelezen. Concurrency-harmless dus. Evenzo voor de session semi-singleton: die wordt eenmaal per client-sessie geschreven en daarna enkel uitgelezen, en logischerwijs kan er geen 2e request in een sessie binnenkomen voordat de eerste afgehandeld is anders is het cookie nog niet terug op de client. Theoretisch dus ook concurrency-harmless.

Om deze redenen zag ik dus weinig in een concurrency-probleem. Toch uit de macht der wanhoop maar even een stresstester geschreven vanmiddag die de applicatie met requests ging bestoken vanuit een aantal threads naar keuze. Met 40 spammende threads had ik de QA-applicatie binnen 5 minuten plat, 100% reproduceerbaar. De applicatie liet ook mooi zien dat alle threads rustig 50~100 werkende calls hadden uitgezet, dan even rust, en dan in 1 klap allemaal tegelijk 100% HTTP 500 Internal Server Error. Rond een uur of 6 voor ik naar huis ging even de singleton-accessors voorzien van lockingcode.... en toen kreeg ik op 80 threads moeiteloos 200+ requests uitgezet voordat ik naar huis moest!

Oftewel het probleem lijkt opgelost door 2 simpele lock-blocks op plekken waarvan ik nog steeds niet snap hoe ze multithreaded kunnen kruisen, morgenochtend meer :)

Professionele website nodig?


Verwijderd

Goed om te horen dat het probleem in ieder geval opgelost lijkt te zijn...

De reden zal waarschijnlijk ergens diep in ASP.NET zitten. Wat nog bij me opkwam is het volgende: Zie deze MSDN documentatie, ik heb nooit goed begrepen waar deze property precies voor dient maar als jij je eigen framework hebt geschreven incl. custom IHttpHandler en je daar in de voornoemde prop true teruggeeft (of als dat standaard is voor de aspx handler) zou dat wellicht een threading probleem kunnen opleveren.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Topicstarter
Ik heb geen HttpHandler :) Voor pagina's doe ik hetzelfde als voor de application: in plaats van dat ze direct van System.Web.UI.Page inheriten doen ze dat van een subclass uit m'n framework die dan zelf weer wel inherit van Page. Op die manier vang ik volautomatiek de complete huisstijlrendering, navigatie en securityzaken van een applicatie af zodat die zich alleen nog met de feitelijke business logic van de pagina zelf bezig hoeft te houden :Y)

Professionele website nodig?


  • whoami
  • Registratie: December 2000
  • Laatst online: 11:17
Hoe heb je dat locking geimplementeert in je singleton ?

https://fgheysels.github.io/


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Topicstarter
whoami schreef op donderdag 28 april 2005 @ 21:51:
Hoe heb je dat locking geimplementeert in je singleton ?
Eigenlijk best stupide, namelijk door te locken op iets waarvan ik zeker wist dat het de request niet zou serialiseren, dus niet op de GetType() die je in een singleton zou verwachten:
C#:
1
2
3
4
lock(HttpContext.Current)
{
  return ...;
}

Ik stond er sowieso al verbaasd van te kijken dat dit scheelde ja 8)7

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 07-05 22:49

curry684

left part of the evil twins

Topicstarter
For the record: het heeft vandaag weer tig stresstests overleefd dus lijkt gefixed :)

Professionele website nodig?


  • gorgi_19
  • Registratie: Mei 2002
  • Nu online

gorgi_19

Kruimeltjes zijn weer op :9

curry684 schreef op vrijdag 29 april 2005 @ 16:01:
For the record: het heeft vandaag weer tig stresstests overleefd dus lijkt gefixed :)
* gorgi_19 wordt ook eens wakker en gaat weer eens bijlezen :)

Heb je toevallig destijds ook gekeken naar naar je task manager en de thread count hierbij (aparte kolom) voor het aspnet_wp proces? Bij te veel threads heeft ASP.Net namelijk de neiging om zichzelf volledig op te blazen en dan komt er weinig meer uit. Dit aantal is afhankelijk van het aantal processoren in een pc / server; geen idee of je hier ook naar gekeken hebt en meegenomen in je test?

[ Voor 3% gewijzigd door gorgi_19 op 05-05-2005 08:49 ]

Digitaal onderwijsmateriaal, leermateriaal voor hbo

Pagina: 1