mirror of
https://github.com/gnustep/libs-sqlclient.git
synced 2025-02-15 16:11:42 +00:00
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:
parent
1fdb15cfb0
commit
1f11ea97a9
2 changed files with 162 additions and 110 deletions
|
@ -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
|
||||||
|
|
267
SQLClient.m
267
SQLClient.m
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue