lock safety fixes

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@35832 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2012-11-29 11:40:04 +00:00
parent 1fdb15cfb0
commit 1f11ea97a9
2 changed files with 162 additions and 110 deletions

View file

@ -1,3 +1,8 @@
2012-11-29 Richard Frith-Macdonald <rfm@gnu.org>
* Wrap more code in exception handlers where there is any potential
for an exception in a lock protected region.
2012-11-10 Niels Grewe <niels.grewe@halbordnung.de> 2012-11-10 Niels Grewe <niels.grewe@halbordnung.de>
* GNUmakefile: Link against $(FND_LIBS) and $(OBJC_LIBS) instead * GNUmakefile: Link against $(FND_LIBS) and $(OBJC_LIBS) instead

View file

@ -1162,25 +1162,26 @@ static unsigned int maxConnections = 8;
[lock lock]; [lock lock];
if (connected == NO) if (connected == NO)
{ {
if (_connectFails > 1)
{
NSTimeInterval delay;
NSTimeInterval elapsed;
/* If we have repeated connection failures, we enforce a
* delay of up to 30 seconds between connection attempts
* to avoid overloading the system with too frequent
* connection attempts.
*/
delay = (_connectFails < 30) ? _connectFails : 30;
elapsed = GSTickerTimeNow() - _lastOperation;
if (elapsed < delay)
{
[NSThread sleepForTimeInterval: delay - elapsed];
}
}
NS_DURING NS_DURING
{ {
if (_connectFails > 1)
{
NSTimeInterval delay;
NSTimeInterval elapsed;
/* If we have repeated connection failures, we enforce a
* delay of up to 30 seconds between connection attempts
* to avoid overloading the system with too frequent
* connection attempts.
*/
delay = (_connectFails < 30) ? _connectFails : 30;
elapsed = GSTickerTimeNow() - _lastOperation;
if (elapsed < delay)
{
[NSThread sleepForTimeInterval: delay - elapsed];
}
}
[self backendConnect]; [self backendConnect];
/* On establishng a new connection, we must restore any /* On establishng a new connection, we must restore any
* listen instructions in the backend. * listen instructions in the backend.
@ -1284,22 +1285,32 @@ static unsigned int maxConnections = 8;
NSMutableString *s = [[NSMutableString new] autorelease]; NSMutableString *s = [[NSMutableString new] autorelease];
[lock lock]; [lock lock];
[s appendFormat: @"Database - %@\n", [self clientName]]; NS_DURING
[s appendFormat: @" Name - %@\n", [self name]];
[s appendFormat: @" DBase - %@\n", [self database]];
[s appendFormat: @" DB User - %@\n", [self user]];
[s appendFormat: @" Password - %@\n",
[self password] == nil ? @"unknown" : @"known"];
[s appendFormat: @" Connected - %@\n", connected ? @"yes" : @"no"];
[s appendFormat: @" Transaction - %@\n", _inTransaction ? @"yes" : @"no"];
if (_cache == nil)
{ {
[s appendString: @"\n"]; [s appendFormat: @"Database - %@\n", [self clientName]];
[s appendFormat: @" Name - %@\n", [self name]];
[s appendFormat: @" DBase - %@\n", [self database]];
[s appendFormat: @" DB User - %@\n", [self user]];
[s appendFormat: @" Password - %@\n",
[self password] == nil ? @"unknown" : @"known"];
[s appendFormat: @" Connected - %@\n", connected ? @"yes" : @"no"];
[s appendFormat: @" Transaction - %@\n",
_inTransaction ? @"yes" : @"no"];
if (_cache == nil)
{
[s appendString: @"\n"];
}
else
{
[s appendFormat: @" Cache - %@\n", _cache];
}
} }
else NS_HANDLER
{ {
[s appendFormat: @" Cache - %@\n", _cache]; [lock unlock];
[localException raise];
} }
NS_ENDHANDLER
[lock unlock]; [lock unlock];
return s; return s;
} }
@ -1838,26 +1849,26 @@ static unsigned int maxConnections = 8;
- (NSInteger) simpleExecute: (NSArray*)info - (NSInteger) simpleExecute: (NSArray*)info
{ {
NSString *statement;
NSInteger result; NSInteger result;
BOOL isCommit = NO;
BOOL isRollback = NO;
[lock lock]; [lock lock];
statement = [info objectAtIndex: 0];
if ([statement isEqualToString: commitString])
{
isCommit = YES;
}
if ([statement isEqualToString: rollbackString])
{
isRollback = YES;
}
NS_DURING NS_DURING
{ {
NSTimeInterval start = 0.0; NSTimeInterval start = 0.0;
NSString *statement;
BOOL isCommit = NO;
BOOL isRollback = NO;
statement = [info objectAtIndex: 0];
if ([statement isEqualToString: commitString])
{
isCommit = YES;
}
if ([statement isEqualToString: rollbackString])
{
isRollback = YES;
}
if (_duration >= 0) if (_duration >= 0)
{ {
@ -2877,17 +2888,26 @@ static unsigned int maxConnections = 8;
- (void) setCache: (GSCache*)aCache - (void) setCache: (GSCache*)aCache
{ {
[lock lock]; [lock lock];
if (_cacheThread != nil) NS_DURING
{ {
[_cache setDelegate: nil]; if (_cacheThread != nil)
{
[_cache setDelegate: nil];
}
[aCache retain];
[_cache release];
_cache = aCache;
if (_cacheThread != nil)
{
[_cache setDelegate: self];
}
} }
[aCache retain]; NS_HANDLER
[_cache release];
_cache = aCache;
if (_cacheThread != nil)
{ {
[_cache setDelegate: self]; [lock unlock];
[localException raise];
} }
NS_ENDHANDLER
[lock unlock]; [lock unlock];
} }
@ -2906,17 +2926,26 @@ static unsigned int maxConnections = 8;
aThread = mainThread; aThread = mainThread;
} }
[lock lock]; [lock lock];
if (_cacheThread != nil) NS_DURING
{ {
[_cache setDelegate: nil]; if (_cacheThread != nil)
{
[_cache setDelegate: nil];
}
[aThread retain];
[_cacheThread release];
_cacheThread = aThread;
if (_cacheThread != nil)
{
[_cache setDelegate: self];
}
} }
[aThread retain]; NS_HANDLER
[_cacheThread release];
_cacheThread = aThread;
if (_cacheThread != nil)
{ {
[_cache setDelegate: self]; [lock unlock];
[localException raise];
} }
NS_ENDHANDLER
[lock unlock]; [lock unlock];
} }
@end @end
@ -3342,34 +3371,43 @@ validName(NSString *name)
name = validName(name); name = validName(name);
[lock lock]; [lock lock];
if (nil == _observers) NS_DURING
{ {
_observers = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks, if (nil == _observers)
NSObjectMapValueCallBacks, 0);
_names = [NSCountedSet new];
}
set = (NSMutableSet*)NSMapGet(_observers, (void*)anObserver);
if (nil == set)
{
set = [NSMutableSet new];
NSMapInsert(_observers, anObserver, set);
[set release];
}
if (nil == [set member: name])
{
NSUInteger count = [_names countForObject: name];
[set addObject: name];
[_names addObject: name];
if (0 == count)
{ {
[self backendListen: name]; _observers = NSCreateMapTable(NSNonRetainedObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
_names = [NSCountedSet new];
} }
set = (NSMutableSet*)NSMapGet(_observers, (void*)anObserver);
if (nil == set)
{
set = [NSMutableSet new];
NSMapInsert(_observers, anObserver, set);
[set release];
}
if (nil == [set member: name])
{
NSUInteger count = [_names countForObject: name];
[set addObject: name];
[_names addObject: name];
if (0 == count)
{
[self backendListen: name];
}
}
[[NSNotificationCenter defaultCenter] addObserver: anObserver
selector: aSelector
name: name
object: self];
} }
[[NSNotificationCenter defaultCenter] addObserver: anObserver NS_HANDLER
selector: aSelector {
name: name [lock unlock];
object: self]; [localException raise];
}
NS_ENDHANDLER
[lock unlock]; [lock unlock];
} }
@ -3394,41 +3432,50 @@ validName(NSString *name)
name = validName(name); name = validName(name);
} }
[lock lock]; [lock lock];
if (_observers != nil) NS_DURING
{ {
NSNotificationCenter *nc; if (_observers != nil)
NSMutableSet *set; {
NSEnumerator *e; NSNotificationCenter *nc;
NSMutableSet *set;
NSEnumerator *e;
nc = [NSNotificationCenter defaultCenter]; nc = [NSNotificationCenter defaultCenter];
set = (NSMutableSet*)NSMapGet(_observers, (void*)anObserver); set = (NSMutableSet*)NSMapGet(_observers, (void*)anObserver);
if (nil == name) if (nil == name)
{
e = [[set allObjects] objectEnumerator];
name = [e nextObject];
}
else
{
name = [[name retain] autorelease];
}
while (nil != name)
{
if (nil != [set member: name])
{ {
[nc removeObserver: anObserver e = [[set allObjects] objectEnumerator];
name: name name = [e nextObject];
object: self]; }
[[name retain] autorelease]; else
[set removeObject: name]; {
[_names removeObject: name]; name = [[name retain] autorelease];
if (0 == [_names countForObject: name]) }
{ while (nil != name)
[self backendUnlisten: name]; {
} if (nil != [set member: name])
{
[nc removeObserver: anObserver
name: name
object: self];
[[name retain] autorelease];
[set removeObject: name];
[_names removeObject: name];
if (0 == [_names countForObject: name])
{
[self backendUnlisten: name];
}
}
name = [e nextObject];
} }
name = [e nextObject];
} }
} }
NS_HANDLER
{
[lock unlock];
[localException raise];
}
NS_ENDHANDLER
[lock unlock]; [lock unlock];
} }
@end @end