deadserious / iwelite

Automatically exported from code.google.com/p/iwelite
Other
1 stars 1 forks source link

Serious bug in LockSession hangs app when there are multiple threads. RESOLVED. #8

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
In ArcIWWebModuleBridge, method TArcIWWebModuleBridge.LockSession, a 
coding problem results in a serious threading problem.

The method locks the global list of sessions, walks the list to find the 
desired session, locks the session, then unlocks the global list.

The problem is that the call to lock the session is a blocking call.  This 
means that while waiting for that lock, the global GSessions list is 
locked.

This further means that the session can never be unlocked, as the 
UnlockSessions method needs to lock GSessions before the unlock can 
proceed.  Thus you have a deadlock.

So as soon as there are two threads making requests from the same session 
simultaneously, this bug basically locks up the Intraweb application.

The resolution is simple:  alter LockSessions so that it looks up the 
session, then releases the lock on GSessions, and THEN locks the session.

Here is the modified routine:

function TArcIWWebModuleBridge.LockSession(const AppID: string): 
TIWApplication;
var
  ls : TList;
  i : integer;
begin
  Result := nil;
  ls := GSessions.LockList;
  try
    for i := 0 to ls.Count-1 do
      if TIWApplication(ls[i]).AppID = AppID then
      begin
        Result := ls[i];
        break;
      end;
//dbr:  WRONG!  Result.Lock is a blocking call--you do NOT
//      want to call it while GSessions is locked.  Will result
//      in a deadlock as soon as there are two active threads for
//      the same session.
//dbr    if Result <> nil then
//dbr      Result.Lock;
  finally
    GSessions.UnlockList;
  end;

//dbr start
  try
    if Result <> nil then begin
      Result.Lock;
    end;
  except
    Result := nil;
  end;
//dbr end

  if Result = nil then
    raise EArcIWBridgeSessionNotFound.Create('Session not found for 
AppID: '+AppID+'. Session may have expired.');
end;

Original issue reported on code.google.com by dbrue...@gmail.com on 30 Apr 2009 at 4:43