Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


ID: 16790, TSession can hangup a multithreaded application

by Peter Laman Email: Anonymous


Due to a bug in exception recovery, TSession can hangup a multithreaded application, when the session can't be made the current session.
Download Details
FTP  download also available
CDN Login Required to Download. (You will be redirected to the login page if you click on the Download Link)
To download this, you must have registered:
A free membership

For Delphi, Version 5.0  to 6.0 237 downloads
Copyright: No significant restrictions


Size: 51,867 bytes
Updated on Tue, 23 Oct 2001 02:46:35 GMT
Originally uploaded on Tue, 23 Oct 2001 02:44:57 GMT
SHA1 Hash: E79F954E91631494EC39EC7DFFE2BBFE3E6A3DDC
MD5 Hash: E93242F5D632C62D96814B3D112BB138

    Explore the files in this upload

Description
Note: See codesnippet 3 at the bottom for a patch, if you whish to skip the description.

In a multithreading application, each thread that wants to use the BDE needs to create an instance of TSession of its own. The TSession synchronizes access to its thread-shared resources with a cricical section. This critical section is entered with the TSession.LockSession method:

procedure TSession.LockSession;
begin
if FLockCount = 0 then
begin
EnterCriticalSection(FCSect);
Inc(FLockCount);
MakeCurrent;
end
else
Inc(FLockCount);
end;
(codesnippet 1)

This method is paired with UnlockSession and used in constructs like:

LockSession;
try
{ Do whatever requires the session to be lock }
finally
UnlockSession;
end;
(codesnippet 2)

The try/finally should guarantee that the locked session will also be unlocked, also in the case of an exception.

Let's take a closer look at the LockSession implementation. The call to MakeCurrent makes the session the current session. Suppose the MakeCurrent method raises an exception. Since MakeCurrent is called after entering the critical section (see codesnippet 1), the session will be locked. But, since the call to LockSession, in codesnippet 2, appears before the try, the UnlockSession will never be executed, Thus the session remains locked forever. In a single-threaded application, you won't notice this, because the thread can always re-enter the critical section it has already enter. But in a multithreaded application, this bug will cause all other threads trying to lock the session to wait infinitely.

Now will this ever happen? Yes, it will. In an app that uses Paradox tables, I tried to set the PrivateDir of the TSession. However, it the directory was already in use. This causes the MakeCurrent call to fail. Bingo.

The following modification to LockSession will fix the problem:

procedure TSession.LockSession;
begin
if FLockCount = 0 then
begin
EnterCriticalSection(FCSect);
Inc(FLockCount);
try
MakeCurrent;
except
UnlockSession;
raise;
end;
end
else
Inc(FLockCount);
end;
(codesnippet 3)

   Latest Comments  View All Add New

Move mouse over comment to see the full text

Server Response from: ETNACDC03