Many fixups/alterations to launch/shutdown of processes. Removed the 'strict' option to enforce a prefix on defaults keys, since it was really never used and just complicated things.

This commit is contained in:
Richard Frith-Macdonald 2020-07-03 11:50:25 +01:00
parent dde42c13a1
commit f04f1292a3
12 changed files with 120 additions and 109 deletions

View file

@ -32,9 +32,6 @@
#if !defined(EC_DEFAULTS_PREFIX)
#define EC_DEFAULTS_PREFIX nil
#endif
#if !defined(EC_DEFAULTS_STRICT)
#define EC_DEFAULTS_STRICT NO
#endif
#if !defined(EC_EFFECTIVE_USER)
#define EC_EFFECTIVE_USER nil
#endif
@ -74,8 +71,7 @@ main()
{
pref = @"";
}
defs = [NSUserDefaults userDefaultsWithPrefix: pref
strict: EC_DEFAULTS_STRICT];
defs = [NSUserDefaults userDefaultsWithPrefix: pref];
dict = [defs dictionaryForKey: @"WellKnownHostNames"];
if (nil != dict)
{

View file

@ -204,6 +204,7 @@ desiredName(Desired state)
unsigned terminationCount; // Terminations during startup
int terminationStatus; // Last exit status
NSTimeInterval registrationDate; // Time of process registration
NSTimeInterval awakenedDate; // When the process was awakened
NSTimeInterval deferredDate; // Deferred re-launch interval
NSTimeInterval queuedDate; // When queued for launch
NSTimeInterval stableDate; // Has been running for a while
@ -221,6 +222,7 @@ desiredName(Desired state)
+ (void) processQueue;
+ (void) remove: (NSString*)name;
- (BOOL) autolaunch;
- (void) awakened;
- (BOOL) checkActive;
- (BOOL) checkAlive;
- (void) clearClient: (EcClientI*)c cleanly: (BOOL)unregisteredOrTransient;
@ -333,6 +335,8 @@ desiredName(Desired state)
- (EcClientI*) findIn: (NSArray*)a
byObject: (id)s;
- (NSString*) host;
- (void) housekeeping: (NSTimer*)t;
- (void) _housekeeping: (NSTimer*)t;
- (void) information: (NSString*)inf
from: (NSString*)s
type: (EcLogType)t;
@ -356,19 +360,19 @@ desiredName(Desired state)
- (void) quitAll;
- (void) quitAll: (NSDate*)by;
- (void) requestConfigFor: (id<CmdConfig>)c;
- (NSData*) registerClient: (id<CmdClient>)c
- (NSData*) registerClient: (id)c
identifier: (int)p
name: (NSString*)n
transient: (BOOL)t;
- (void) reply: (NSString*) msg to: (NSString*)n from: (NSString*)c;
- (void) terminate: (NSDate*)by;
- (void) _terminate: (NSTimer*)t;
- (void) housekeeping: (NSTimer*)t;
- (void) _housekeeping: (NSTimer*)t;
- (NSMutableArray*) unconfiguredClients;
- (void) unregisterByObject: (id)obj;
- (void) unregisterClient: (EcClientI*)o;
- (void) update;
- (void) updateConfig: (NSData*)data;
- (void) woken: (id)obj;
@end
@ -579,6 +583,11 @@ desiredName(Desired state)
return [[conf objectForKey: @"Auto"] boolValue];
}
- (void) awakened
{
awakenedDate = [NSDate timeIntervalSinceReferenceDate];
}
/* Check to see if there is an active process connected (or which connects
* when we contact it and ask it to).
*/
@ -671,7 +680,7 @@ desiredName(Desired state)
clientLost = YES;
}
/* The connection to the client went away, which implies that the process
* was connected/registred and we must either be stopping already or need
* was connected/registered and we must either be stopping already or need
* to stop (expect the process to die soon).
* So either way we should trigger the -stopping: timeout handler to
* check for the end of the process and to ensure that we try again if
@ -1109,14 +1118,15 @@ NSLog(@"startup completed for %@", self);
startingTimer = nil;
startingDate = 0.0;
starting = NO;
if (Dead == desired)
{
/* It is not desired that this process should be running:
* initiate a shutdown.
*/
[self stop];
}
}
if (Dead == desired)
{
/* It is not desired that this process should be running:
* initiate a shutdown.
*/
[self stop];
}
[self progress];
[LaunchInfo processQueue]; // Maybe we can launch more now
}
@ -1584,6 +1594,7 @@ NSLog(@"startup completed for %@", self);
[stoppingTimer invalidate];
stoppingTimer = nil;
awakenedDate = 0.0;
abortDate = 0.0;
stopping = NO;
DESTROY(terminateBy); // Termination completed
@ -1655,10 +1666,6 @@ NSLog(@"startup completed for %@", self);
{
/* Maximum time for clean shutdown has passed.
*/
if (client != nil)
{
[self clearClient: client cleanly: NO];
}
[[NSNotificationCenter defaultCenter]
removeObserver: self
name: NSTaskDidTerminateNotification
@ -1670,7 +1677,15 @@ NSLog(@"startup completed for %@", self);
kill(identifier, SIGKILL);
identifier = 0;
}
[self stopped];
if (client != nil)
{
[self clearClient: client cleanly: NO];
}
else
{
[self stopped];
}
return;
}
else
{
@ -4023,12 +4038,12 @@ NSLog(@"Problem %@", localException);
}
}
- (NSData*) registerClient: (id<CmdClient>)c
- (NSData*) registerClient: (id)c
identifier: (int)p
name: (NSString*)n
transient: (BOOL)t
{
LaunchInfo *l = [LaunchInfo existing: n];
int pid;
NSMutableDictionary *dict;
EcClientI *obj;
EcClientI *old;
@ -4047,11 +4062,9 @@ NSLog(@"Problem %@", localException);
errorDescription: 0];
}
pid = [c processIdentifier];
/* Do we already have this registered?
*/
if ([l processIdentifier] == pid && (obj = [l client]) != nil)
if ([l processIdentifier] == p && (obj = [l client]) != nil)
{
[self logChange: @"re-registered" for: [l name]];
if ([l stable] == YES)
@ -4074,7 +4087,7 @@ NSLog(@"Problem %@", localException);
RELEASE(obj);
[clients sortUsingSelector: @selector(compare:)];
[obj setProcessIdentifier: pid];
[obj setProcessIdentifier: p];
if (nil == l)
{
@ -4904,5 +4917,17 @@ NSLog(@"Problem %@", localException);
[self newConfig: newConfig];
}
- (void) woken: (id)obj
{
EcClientI *o = [self findIn: clients byObject: obj];
if (o != nil)
{
LaunchInfo *l = [launchInfo objectForKey: [o name]];
[l awakened];
}
}
@end

View file

@ -72,8 +72,7 @@ static NSString *controlName = nil;
defs = [NSUserDefaults prefixedDefaults];
if (nil == defs)
{
defs = [NSUserDefaults userDefaultsWithPrefix: nil
strict: NO];
defs = [NSUserDefaults userDefaultsWithPrefix: nil];
}
name = [defs stringForKey: @"ControlHost"];
if (nil != name)

View file

@ -147,7 +147,10 @@ static NSArray *modes;
id<CmdLogger> server;
server = (id<CmdLogger>)[EcProc server: name];
[server registerClient: self name: cmdLogName() transient: NO];
[server registerClient: self
identifier: [[NSProcessInfo processInfo] processIdentifier]
name: cmdLogName()
transient: NO];
}
/* Should only be called on main thread, but doesn't matter.
@ -210,6 +213,11 @@ static NSArray *modes;
return s;
}
- (BOOL) ecDidAwaken
{
return YES;
}
/**
* Internal flush operation ... writes data out from us, but
* doesn't try any further. Only called in main thread.

View file

@ -153,9 +153,21 @@ typedef enum {
/** Messages that the Command server may send to clients.
*/
@protocol CmdClient <CmdPing,CmdConfig>
/** Passes a property list message to the client (eg from the Console).
*/
- (oneway void) cmdMesgData: (in bycopy NSData*)dat from: (NSString*)name;
/** Tells the client to shut down.
*/
- (oneway void) cmdQuit: (NSInteger)status;
/** Asks the client for its process identifier.
*/
- (int) processIdentifier;
/** Asks the client whether it is awake (-ecAwaken has been called)
*/
- (BOOL) ecDidAwaken;
/** Instructs the client process to connect and re-register with the Command
* server.
*/
- (oneway void) ecReconnect;
@end
@ -170,9 +182,11 @@ typedef enum {
type: (EcLogType)t
for: (id)o;
- (bycopy NSData*) registerClient: (id)c
identifier: (int)p
name: (NSString*)n
transient: (BOOL)t;
- (void) unregisterByObject: (id)obj;
- (void) woken: (id)obj;
@end
@protocol Console <NSObject>
@ -180,8 +194,8 @@ typedef enum {
@end
/** Messages that clients may send to the server.
* NB. The -registerClient:name:transient: method must be sent before
* the -command:to:from: or -reply:to:from: methods.
* NB. The -registerClient:identifier:name:transient: method must be sent
* before the -command:to:from: or -reply:to:from: methods.
*/
@protocol Command <CmdLogger,CmdConfig,EcAlarmDestination>
@ -208,7 +222,8 @@ typedef enum {
/** Registers as a client process of the Command server.
*/
- (bycopy NSData*) registerClient: (id<CmdClient>)c
- (bycopy NSData*) registerClient: (id)c
identifier: (int)p
name: (NSString*)n
transient: (BOOL)t;
@ -236,6 +251,12 @@ typedef enum {
* time your software needs it.
*/
- (bycopy NSData *) configurationFor: (NSString *)name;
/** Informs the Command server that a previously registered client considers
* itself to have started up and to now be stable.
*/
- (void) woken: (id)obj;
@end
/*

View file

@ -105,9 +105,6 @@ static NSInteger descriptorsMaximum = 0;
#if !defined(EC_DEFAULTS_PREFIX)
#define EC_DEFAULTS_PREFIX nil
#endif
#if !defined(EC_DEFAULTS_STRICT)
#define EC_DEFAULTS_STRICT NO
#endif
#if !defined(EC_EFFECTIVE_USER)
#define EC_EFFECTIVE_USER nil
#endif
@ -1600,9 +1597,7 @@ findMode(NSDictionary* d, NSString* s)
prf = @"";
}
ASSIGN(cmdDefs, [NSUserDefaults
userDefaultsWithPrefix: prf
strict: EC_DEFAULTS_STRICT]);
ASSIGN(cmdDefs, [NSUserDefaults userDefaultsWithPrefix: prf]);
defs = [EcDefaultRegistration merge: defs];
[cmdDefs registerDefaults: defs];
@ -1676,9 +1671,7 @@ findMode(NSDictionary* d, NSString* s)
NSLog(@"You must be '%@' to run this.", cmdUser);
exit(1);
}
ASSIGN(cmdDefs, [NSUserDefaults
userDefaultsWithPrefix: prf
strict: EC_DEFAULTS_STRICT]);
ASSIGN(cmdDefs, [NSUserDefaults userDefaultsWithPrefix: prf]);
if (defs != nil)
{
[cmdDefs registerDefaults: defs];
@ -3466,6 +3459,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
NSData *d;
d = [proxy registerClient: self
identifier: [self processIdentifier]
name: cmdLogName()
transient: cmdIsTransient];
r = [NSPropertyListSerialization
@ -3806,6 +3800,17 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
[self triggerCmdTimeout]; /* make sure that regular timers run. */
NS_DURING
[cmdServer woken: self];
NS_HANDLER
DESTROY(cmdServer);
NS_ENDHANDLER
if (nil == cmdServer)
{
DESTROY(cmdLast); // Allow immediate retry
[self cmdNewServer];
}
loop = [NSRunLoop currentRunLoop];
future = [NSDate distantFuture];
while (YES == [EcProcConnection isValid])
@ -3868,6 +3873,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
{
NS_DURING
[cmdServer registerClient: self
identifier: [self processIdentifier]
name: cmdLogName()
transient: cmdIsTransient];
NS_HANDLER

View file

@ -32,9 +32,6 @@
#if !defined(EC_DEFAULTS_PREFIX)
#define EC_DEFAULTS_PREFIX nil
#endif
#if !defined(EC_DEFAULTS_STRICT)
#define EC_DEFAULTS_STRICT NO
#endif
#if !defined(EC_EFFECTIVE_USER)
#define EC_EFFECTIVE_USER nil
#endif
@ -61,8 +58,7 @@ defaults()
{
pref = @"";
}
ASSIGN(defs, [NSUserDefaults userDefaultsWithPrefix: pref
strict: EC_DEFAULTS_STRICT]);
ASSIGN(defs, [NSUserDefaults userDefaultsWithPrefix: pref]);
dict = [defs dictionaryForKey: @"WellKnownHostNames"];
if (nil != dict)
{
@ -142,10 +138,11 @@ EcTestConnect(NSString *name, NSString *host, NSTimeInterval timeout)
{
if (YES == [(EcProcess*)proxy cmdIsClient])
{
if (NO == [(EcProcess*)proxy cmdIsConnected])
if (NO == [(EcProcess*)proxy ecDidAwaken])
{
/* We must wait for the connected process to register
* with the Command server and configure itself.
* with the Command server (if it's not transient) and
* configure itself and wake up.
*/
proxy = nil;
[NSThread sleepForTimeInterval: 0.1];
@ -243,4 +240,3 @@ EcTestShutdown(id<EcTest> process, NSTimeInterval timeout)
return YES;
}

View file

@ -47,18 +47,14 @@
*/
+ (void) setDefaultLifetime: (NSTimeInterval)t;
/** Returns a proxy to the shared user defaults instance, which will use
/** Returns a proxy to the shared user defaults instance, which will allow
* aPrefix at the start of every key.<br />
* If aPrefix is nil, the string given by the EcUserDefaultsPrefix user
* default is used.<br />
* If the enforcePrefix flag is YES, the prefix is strictly enforced,
* otherwise the system will read defaults using the unprefixed key
* if no value is found for the prefixed key. Similary, when setting
* values, this flag will force the prefix to be prepended to any key
* where it is not already present.
* The proxy will read defaults using the unprefixed key if no value is
* found for the prefixed key.
*/
+ (NSUserDefaults*) userDefaultsWithPrefix: (NSString*)aPrefix
strict: (BOOL)enforcePrefix;
+ (NSUserDefaults*) userDefaultsWithPrefix: (NSString*)aPrefix;
/** Returns a dictionary listing all the command override keys for which
* values are currently set. The values in the dictionary are the timestamps
@ -81,12 +77,7 @@
*/
- (NSString*) defaultsPrefix;
/** returns YES if this is a proxy which enforces the use of the prefix on
* defaults keys.
*/
- (BOOL) enforcePrefix;
/** Convenience method to prepend the pefix to the supplied aKey value
/** Convenience method to prepend the prefix to the supplied aKey value
* if it is not already present.
*/
- (NSString*) key: (NSString*)aKey;

View file

@ -48,9 +48,8 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
{
NSUserDefaults *defs;
NSString *prefix;
BOOL enforce;
}
- (id) initWithPrefix: (NSString*)p strict: (BOOL)s;
- (id) initWithPrefix: (NSString*)p;
- (NSString*) _getKey: (NSString*)baseKey;
@end
@ -143,7 +142,7 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
{
aKey = [prefix stringByAppendingString: aKey];
}
if (NO == enforce && nil == [defs objectForKey: aKey])
if (nil == [defs objectForKey: aKey])
{
/* Nothing found for key ... try without the prefix.
*/
@ -159,12 +158,11 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
return nil;
}
- (id) initWithPrefix: (NSString*)p strict: (BOOL)s
- (id) initWithPrefix: (NSString*)p
{
NSMutableArray *list;
[lock lock];
enforce = s;
defs = [[NSUserDefaults standardUserDefaults] retain];
if (0 == [p length])
{
@ -238,41 +236,39 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
- (void) setBool: (BOOL)value forKey: (NSString*)aKey
{
[defs setBool: value forKey: (enforce ? [self key: aKey] : aKey)];
[defs setBool: value forKey: aKey];
}
- (BOOL) setCommand: (id)val forKey: (NSString*)key
{
return [defs setCommand: val forKey: (enforce ? [self key: key] : key)];
return [defs setCommand: val forKey: key];
}
- (BOOL) setCommand: (id)val
forKey: (NSString*)key
lifetime: (NSTimeInterval)t
{
return [defs setCommand: val
forKey: (enforce ? [self key: key] : key)
lifetime: t];
return [defs setCommand: val forKey: key lifetime: t];
}
- (void) setDouble: (double)value forKey: (NSString*)aKey
{
[defs setDouble: value forKey: (enforce ? [self key: aKey] : aKey)];
[defs setDouble: value forKey: aKey];
}
- (void) setFloat: (float)value forKey: (NSString*)aKey
{
[defs setFloat: value forKey: (enforce ? [self key: aKey] : aKey)];
[defs setFloat: value forKey: aKey];
}
- (void) setInteger: (NSInteger)value forKey: (NSString*)aKey
{
[defs setInteger: value forKey: (enforce ? [self key: aKey] : aKey)];
[defs setInteger: value forKey: aKey];
}
- (void) setObject: (id)anObject forKey: (NSString*)aKey
{
[defs setObject: anObject forKey: (enforce ? [self key: aKey] : aKey)];
[defs setObject: anObject forKey: aKey];
}
- (NSArray*) stringArrayForKey: (NSString*)aKey
@ -318,10 +314,9 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
}
+ (NSUserDefaults*) userDefaultsWithPrefix: (NSString*)aPrefix
strict: (BOOL)enforcePrefix
{
return (NSUserDefaults*)[[[EcUserDefaults alloc] initWithPrefix:
aPrefix strict: enforcePrefix] autorelease];
return (NSUserDefaults*)[[[EcUserDefaults alloc]
initWithPrefix: aPrefix] autorelease];
}
- (NSDictionary*) commandExpiries
@ -354,11 +349,6 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
return nil; // No prefix in use ... this is not a proxy
}
- (BOOL) enforcePrefix
{
return NO; // No prefix to enforce ... this is not a proxy
}
- (NSString*) key: (NSString*)aKey
{
NSString *prefix = [self defaultsPrefix];
@ -441,13 +431,6 @@ static NSTimeInterval defaultDuration = (72.0 * 60.0 * 60.0);
BOOL changed = NO;
id old;
if (YES == [self enforcePrefix])
{
/* Make sure prefix is used if we have one set.
*/
key = [self key: key];
}
[lock lock];
old = [overrides objectForKey: key];
if (old != val && NO == [old isEqual: val])

View file

@ -32,9 +32,6 @@
#if !defined(EC_DEFAULTS_PREFIX)
#define EC_DEFAULTS_PREFIX nil
#endif
#if !defined(EC_DEFAULTS_STRICT)
#define EC_DEFAULTS_STRICT NO
#endif
#if !defined(EC_EFFECTIVE_USER)
#define EC_EFFECTIVE_USER nil
#endif
@ -68,8 +65,7 @@ main()
{
pref = @"";
}
defs = [NSUserDefaults userDefaultsWithPrefix: pref
strict: EC_DEFAULTS_STRICT];
defs = [NSUserDefaults userDefaultsWithPrefix: pref];
dict = [defs dictionaryForKey: @"WellKnownHostNames"];
if (nil != dict)
{

View file

@ -32,9 +32,6 @@
#if !defined(EC_DEFAULTS_PREFIX)
#define EC_DEFAULTS_PREFIX nil
#endif
#if !defined(EC_DEFAULTS_STRICT)
#define EC_DEFAULTS_STRICT NO
#endif
#if !defined(EC_EFFECTIVE_USER)
#define EC_EFFECTIVE_USER nil
#endif
@ -67,8 +64,7 @@ main()
{
pref = @"";
}
defs = [NSUserDefaults userDefaultsWithPrefix: pref
strict: EC_DEFAULTS_STRICT];
defs = [NSUserDefaults userDefaultsWithPrefix: pref];
if ([defs boolForKey: @"Help"] || [defs boolForKey: @"help"]
|| [[[NSProcessInfo processInfo] arguments] containsObject: @"--Help"]

View file

@ -11,11 +11,6 @@
# May be used to define an Objective-C string literal to be used as the
# prefix when looking up keys in the defaults/configuration system.
#
# EC_DEFAULTS_STRICT
# May be used to define an Objective-C boolean literal to be used to
# control whether configuration keys are used only with the prefix
# or whether values for keys without the prefix are also looked up.
#
# EC_EFFECTIVE_USER
# May be used to define an Objective-C string literal to be used to
# specify the name of the user to run all EcProcess programs.
@ -28,7 +23,6 @@
ECCL_CPPFLAGS += \
'-DEC_DEFAULTS_PREFIX=@"XX"'\
'-DEC_DEFAULTS_STRICT=NO'\
'-DEC_EFFECTIVE_USER=@"dummy"'\
# Command_CPPFLAGS ...