Attempted deadlock fix

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@38606 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2015-06-09 16:47:36 +00:00
parent 9282a5134d
commit c47c323a7f
2 changed files with 62 additions and 5 deletions

View file

@ -1,3 +1,9 @@
2015-06-09 Richard Frith-Macdonald <rfm@gnu.org>
* SQLClient.m: Fix reace condition spotted by Wolfgang and change
purge operation to avoid disconnecting clients while the class lock
is locked.
2015-05-28 Richard Frith-Macdonald <rfm@gnu.org>
* SQLClient.h: Add pool purge control method.

View file

@ -903,10 +903,15 @@ static int poolConnections = 0;
+ (void) purgeConnections: (NSDate*)since
{
NSHashEnumerator e;
NSMutableArray *a = nil;
SQLClient *o;
unsigned int connectionCount = 0;
NSTimeInterval t = [since timeIntervalSinceReferenceDate];
NSTimeInterval t;
t = (nil == since) ? 0.0 : [since timeIntervalSinceReferenceDate];
/* Find clients we may want to disconnect.
*/
[clientsLock lock];
e = NSEnumerateHashTable(clientsHash);
while (nil != (o = (SQLClient*)NSNextHashEnumeratorItem(&e)))
@ -915,12 +920,20 @@ static int poolConnections = 0;
{
NSTimeInterval when = o->_lastOperation;
if (when < o->_lastStart)
{
when = o->_lastStart;
}
if (when < t && YES == o->connected)
{
[o disconnect];
if (nil == a)
{
a = [NSMutableArray array];
}
[a addObject: o];
}
}
if ([o connected] == YES)
else if ([o connected] == YES)
{
connectionCount++;
}
@ -928,6 +941,40 @@ static int poolConnections = 0;
NSEndHashTableEnumeration(&e);
[clientsLock unlock];
/* Disconnect any clients idle too long
*/
while ([a count] > 0)
{
o = [a lastObject];
if ([o->lock tryLock])
{
NSTimeInterval when = o->_lastOperation;
if (when < o->_lastStart)
{
when = o->_lastStart;
}
if (when < t && YES == o->connected)
{
NS_DURING
{
[o disconnect];
if ([o connected] == YES)
{
connectionCount++;
}
}
NS_HANDLER
{
NSLog(@"Problem disconnecting: %@", localException);
}
NS_ENDHANDLER
}
[o->lock unlock];
}
[a removeLastObject];
}
while (connectionCount >= (maxConnections + poolConnections))
{
SQLClient *other = nil;
@ -942,11 +989,15 @@ static int poolConnections = 0;
{
NSTimeInterval when = o->_lastOperation;
if (when < o->_lastStart)
{
when = o->_lastStart;
}
connectionCount++;
if (oldest == 0.0 || when < oldest)
{
oldest = when;
other = o;
ASSIGN(other, o);
}
}
}
@ -959,7 +1010,7 @@ static int poolConnections = 0;
@"Force disconnect of '%@' because max connections (%u) reached",
other, maxConnections];
}
[other disconnect];
[AUTORELEASE(other) disconnect];
}
}