improvements for thread safety ... use main thread for connections

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/ec/trunk@37887 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2014-05-16 16:24:28 +00:00
parent 96d11d9869
commit c4dc8d4489
3 changed files with 90 additions and 44 deletions

View file

@ -1,3 +1,9 @@
2014-05-16 Richard Frith-Macdonald <rfm@gnu.org>
EcAlarmDestination.m: Perform all connection operations in
main thread (forwarding etc) and ensure that we run the
current run loop while waiting for startup and shutdown.
2014-05-14 Richard Frith-Macdonald <rfm@gnu.org>
* EcAlerter.m: fix bug processing alert emails

View file

@ -205,7 +205,8 @@
@end
/** Methods called internally to forward events to the remote target of
* the receiver. These are provided for subclasses to override.
* the receiver.
* These methods must perform themselves in the main thread.
*/
@interface EcAlarmDestination (Forwarding)
/** Forward an alarm event. */

View file

@ -36,6 +36,10 @@
@interface EcAlarmDestination (Private)
/* Make connection to destination host.
*/
- (void) _connect;
/* Loss of connection ... clear destination.
*/
- (void) _connectionBecameInvalid: (id)connection;
@ -123,8 +127,8 @@
{
NSDate *begin;
_host = [host copy];
_name = [name copy];
_host = [host copy];
_name = [name copy];
_alarmLock = [NSRecursiveLock new];
_alarmQueue = [NSMutableArray new];
_alarmsActive = [NSMutableSet new];
@ -137,6 +141,8 @@
begin = [NSDate date];
while (NO == [self isRunning])
{
NSDate *when;
if ([begin timeIntervalSinceNow] < -5.0)
{
NSLog(@"alarm thread failed to start within 5 seconds");
@ -146,7 +152,9 @@
[self release];
return nil;
}
[NSThread sleepForTimeInterval: 0.1];
when = [[NSDate alloc] initWithTimeIntervalSinceNow: 0.1];
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: when];
[when release];
}
}
return self;
@ -295,12 +303,16 @@
begin = [NSDate date];
while (YES == [self isRunning])
{
NSDate *when;
if ([begin timeIntervalSinceNow] < -5.0)
{
NSLog(@"alarm thread failed to stop within 5 seconds");
return;
}
[NSThread sleepForTimeInterval: 0.1];
when = [[NSDate alloc] initWithTimeIntervalSinceNow: 0.1];
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: when];
[when release];
}
}
@ -340,6 +352,47 @@
@implementation EcAlarmDestination (Private)
- (void) _connect
{
if (nil == (id)_destination)
{
if (nil != _name)
{
id proxy;
if (nil == _host)
{
proxy = [NSConnection
rootProxyForConnectionWithRegisteredName: _name
host: _host
usingNameServer:
[NSMessagePortNameServer sharedInstance]];
}
else
{
proxy = [NSConnection
rootProxyForConnectionWithRegisteredName: _name
host: _host
usingNameServer:
[NSSocketPortNameServer sharedInstance]];
}
if (proxy != nil)
{
id connection = [proxy connectionForProxy];
[connection setDelegate: self];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_connectionBecameInvalid:)
name: NSConnectionDidDieNotification
object: connection];
[self setDestination: (id<EcAlarmDestination>)proxy];
}
}
}
}
- (void) _connectionBecameInvalid: (id)connection
{
[self setDestination: nil];
@ -355,43 +408,6 @@
{
if ([_alarmQueue count] > 0)
{
if (nil == (id)_destination)
{
if (nil != _name)
{
id proxy;
if (nil == _host)
{
proxy = [NSConnection
rootProxyForConnectionWithRegisteredName: _name
host: _host
usingNameServer:
[NSMessagePortNameServer sharedInstance]];
}
else
{
proxy = [NSConnection
rootProxyForConnectionWithRegisteredName: _name
host: _host
usingNameServer:
[NSSocketPortNameServer sharedInstance]];
}
if (proxy != nil)
{
id connection = [proxy connectionForProxy];
[connection setDelegate: self];
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_connectionBecameInvalid:)
name: NSConnectionDidDieNotification
object: connection];
[self setDestination: (id<EcAlarmDestination>)proxy];
}
}
}
// Do stuff here
while ([_alarmQueue count] > 0)
@ -461,7 +477,6 @@
[_managedObjects addObject: m];
[self domanageFwd: m];
}
[self alarmFwd: next];
}
}
@ -504,7 +519,7 @@
{
if (YES == [s hasPrefix: m])
{
[self _unmanage: s];
[self unmanageFwd: s];
}
}
}
@ -571,7 +586,14 @@
- (void) alarmFwd: (EcAlarm*)event
{
if (NO == [NSThread isMainThread])
{
[self performSelectorOnMainThread: _cmd withObject: event waitUntilDone: NO];
return;
}
[_alarmLock lock];
NS_DURING
[self _connect];
[_destination alarm: event];
NS_DURING
[_backups makeObjectsPerformSelector: @selector(alarm:)
@ -584,11 +606,19 @@
[self setDestination: nil];
NSLog(@"Problem sending alarm to destination ... %@", localException);
NS_ENDHANDLER
[_alarmLock unlock];
}
- (void) domanageFwd: (NSString*)managedObject
{
if (NO == [NSThread isMainThread])
{
[self performSelectorOnMainThread: _cmd withObject: managedObject waitUntilDone: NO];
return;
}
[_alarmLock lock];
NS_DURING
[self _connect];
[_destination domanage: managedObject];
NS_DURING
[_backups makeObjectsPerformSelector: @selector(domanage:)
@ -601,11 +631,19 @@
[self setDestination: nil];
NSLog(@"Problem with domanage to destination ... %@", localException);
NS_ENDHANDLER
[_alarmLock unlock];
}
- (void) unmanageFwd: (NSString*)managedObject
{
if (NO == [NSThread isMainThread])
{
[self performSelectorOnMainThread: _cmd withObject: managedObject waitUntilDone: NO];
return;
}
[_alarmLock lock];
NS_DURING
[self _connect];
[_destination unmanage: managedObject];
NS_DURING
[_backups makeObjectsPerformSelector: @selector(unmanage:)
@ -618,6 +656,7 @@
[self setDestination: nil];
NSLog(@"Problem with unmanage to destination ... %@", localException);
NS_ENDHANDLER
[_alarmLock unlock];
}
@end