Author: rfm
Date: Fri May 16 18:24:28 2014
New Revision: 37887
URL: http://svn.gna.org/viewcvs/gnustep?rev=37887&view=rev
Log:
improvements for thread safety ... use main thread for connections
Modified:
libs/ec/trunk/ChangeLog
libs/ec/trunk/EcAlarmDestination.h
libs/ec/trunk/EcAlarmDestination.m
Modified: libs/ec/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/ChangeLog?rev=37887&r1=37886&r2=37887&view=diff
==============================================================================
--- libs/ec/trunk/ChangeLog (original)
+++ libs/ec/trunk/ChangeLog Fri May 16 18:24:28 2014
@@ -1,3 +1,9 @@
+2014-05-16 Richard Frith-Macdonald <[email protected]>
+
+ 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 <[email protected]>
* EcAlerter.m: fix bug processing alert emails
Modified: libs/ec/trunk/EcAlarmDestination.h
URL:
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcAlarmDestination.h?rev=37887&r1=37886&r2=37887&view=diff
==============================================================================
--- libs/ec/trunk/EcAlarmDestination.h (original)
+++ libs/ec/trunk/EcAlarmDestination.h Fri May 16 18:24:28 2014
@@ -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. */
Modified: libs/ec/trunk/EcAlarmDestination.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/ec/trunk/EcAlarmDestination.m?rev=37887&r1=37886&r2=37887&view=diff
==============================================================================
--- libs/ec/trunk/EcAlarmDestination.m (original)
+++ libs/ec/trunk/EcAlarmDestination.m Fri May 16 18:24:28 2014
@@ -35,6 +35,10 @@
@interface EcAlarmDestination (Private)
+
+/* Make connection to destination host.
+ */
+- (void) _connect;
/* Loss of connection ... clear destination.
*/
@@ -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
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs