Our application makes heavy use of PPR to give us that wonderful AJAX feel.
Recently we stumbled across a potential race condition within htmldb_Get
What we found was that two consecutive htmldb_Get requests (for example two PPRs done in quick succession) can cause a race condition within htmldb_Get potentially resulting in a null value error.
The cause of this problem is as follows:
Line 172 and 181:
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,100);
These two lines create a timeout which runs htmldb_get_WriteResult() after 100 milliseconds.
Now imagine that two PPRs are run in rapid succession.
This causes a race condition on the global variable gNode!
Execution example:
PPR-1 is executed
PPR-1 creates a timeout and finishes
PPR-1 timeout is now waiting for 100 milliseconds
PPR-2 is executed
PPR-2 creates a timeout and finishes
PPR-2 timeout is waiting for 100 milliseconds
PPR-1 wakes up
PPR-1 runs line 196 ( if(gNode && ... ) )
PPR-1 runs line 199 ( gNode.innerHTML = gResult; )
PPR-2 wakes up
PPR-1 runs line 201 ( gResult = null; )
PPR-2 runs line 196 ( if(gNode && ... ) )
PPR-1 runs line 202 ( gNode = null; )
PPR-2 runs line 199 ( gNode.innerHTML = gResult; )
PPR-2 gets null value error!
Because gNode is global and is modified by both functions it causes this race condition.
One suggested change would be to use setTimeout with a function as a closure as its argument instead of a string.
To implement this, change htmldb_get_WriteResult to something like:
function htmldb_get_WriteResult( updateNode, updateResult ) {
if( updateNode ) {
if( updateNode.nodeName == 'INPUT' || updateNode.nodeName == 'TEXTAREA' ) {
updateNode.value = updateResult;
} else {
updateNode.innerHTML = updateResult;
}
}
}
And modify all instances of:
var ie_HACK = 'htmldb_get_WriteResult()';
setTimeout(ie_HACK,100);
To something like:
setTimeout( function() { htmldb_get_WriteResult( gNode, gResult ); }, 100 );