onConnect race condition against onAppStart
hello all,
one of my flash apps uses remoting within server side 'main.asc' in order to do some internal stuff against one of our php servers.
As you all know, when a remote service call is made, flash won't stop execution nor will wait for the results to arrive, since this is made asynchronously by calling the 'whateverRpcService_Result' function.
put in this way, please consider the following code : when the app first initialises, it connects to out php backbone and retrieves certain data (let's say, initData array) . Every onConnect() event must check that data before accepting or rejecting the connection. So it's vital that "initData" is available to flash when the first onConnect() triggers.
----------------
application.onAppStart = function(){
//... initialise remoting stuff: gateway, get remote service, etc. ...
// .....
// launch remoting php function "gimmeInitData"
myRemoteService.gimmeInitData();
// the responder
this.gimmeInitData_Result = function( returnData ) {
// "returnData" contains the desired "initData" array.
// now my app is ready to accept user connections
yetInitialised = true; // watch this one out
} // responder function ends
} // onAppStart ends
application.onConnect = function () { // some luser logs in
if (typeof(yetInitialised) == "undefined") // onAppStart not fully executed?
{
while(typeof(yetInitialised) == "undefined")
{} // noop , wait until onAppStart defines variable "yetInitialised"
} // fi
......
.....
// proceed with login
.....
.....
} // onConnect ends
------------------------------------------
Now many of you have caught the problem for sure. The problem arises when the application instance gets unloaded ( for example, after X idle minutes, configurable via application.xml file ).
When an app is unloaded, the first onConnect() attemp against it will trigger first an onAppStart(), since that first login attemp has woken up (i.e., loaded) the app.
Now it comes the fun. Since flash is so wonderfully asynchronous, when gimmeInitData remote procedure is called, the onAppStart execution thread continues, and the function ends.
When onAppStart() ends, the triggering onConnect() gets inmediately launched after it.
Given certain network/remoting-php server overload, gimmeInitData can get executed kind of fast, or it could last for several seconds.
If so, it is perfectly possible for onConnect() to start execution before we have arrived to "yetInitialised = true". So "yetInitialised" is yet undefined.
In order to detect this condition, we check typeof(yetInitialised) against "undefined".
This works as expected, and the race condition gets detected.
BUT , and here comes the real problem, when we enter the NOOP loop, where we evaluate "yetInitialised" looking for a change in his undefined condition, the loop lasts forever. Crash Bang Ouch, server to the toilet, 100% cpu use, restart the server, take a coffe, kick the dog, etc.etc. whatsoever....
Fact is, yetInitialised eventually becomes "true", but the loop inside onConnect won't acknowledge such change. Simply speaking, it seems as if when the onConnect function gets instantiated, it reads a copy of the variables within its scope, and since it's managing a COPY of the yetInitialised variable, it doesn't notice when the original variable changes.
In other languages, this could be fixed accessing the real variable throught a pointer. Perhaps some of you could send me any light into this little issue ?
many thanks in advance ,
|