More reliably system shutdown

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/ec/trunk@38302 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2015-01-26 12:50:42 +00:00
parent c30eed0fa0
commit 177efca91b
8 changed files with 103 additions and 31 deletions

View file

@ -1,3 +1,14 @@
2015-01-26 Richard Frith-Macdonald <rfm@gnu.org>
* GNUmakefile.preamble: fixup gcc flag filtering
* EcClientI.h:
* EcClientI.m:
* EcCommand.m:
* EcControl.m:
* EcProcess.h:
* EcProcess.m:
Implement forced kill by -terminate method if a client fails to
close down gracefully within 30 seconds.
2015-01-19 Wolfgang Lux <wolfgang.lux@gmail.com> 2015-01-19 Wolfgang Lux <wolfgang.lux@gmail.com>
* GNUmakefile.preamble: Fix wrong option letter in sed command. * GNUmakefile.preamble: Fix wrong option letter in sed command.

View file

@ -40,9 +40,9 @@
@interface EcClientI : NSObject @interface EcClientI : NSObject
{ {
id<CmdClient> theServer; id<CmdClient> theServer;
id obj; id obj; /* The proxy object of client. */
NSString *name; NSString *name; /* The name of the client. */
NSDate *lastUnanswered; /* Last unanswered ping. */ NSDate *lastUnanswered; /* Last unanswered ping. */
unsigned fwdSequence; /* Last ping sent TO client. */ unsigned fwdSequence; /* Last ping sent TO client. */
unsigned revSequence; /* Last gnip sent BY client. */ unsigned revSequence; /* Last gnip sent BY client. */
NSMutableSet *files; /* Want update info for these. */ NSMutableSet *files; /* Want update info for these. */
@ -50,6 +50,7 @@
BOOL pingOk; /* Can remote end accept ping? */ BOOL pingOk; /* Can remote end accept ping? */
BOOL transient; /* Is this a transient client? */ BOOL transient; /* Is this a transient client? */
BOOL unregistered; /* Has client unregistered? */ BOOL unregistered; /* Has client unregistered? */
int processIdentifier; /* Process ID if known (or 0). */
} }
- (NSComparisonResult) compare: (EcClientI*)other; - (NSComparisonResult) compare: (EcClientI*)other;
- (NSData*) config; - (NSData*) config;
@ -62,9 +63,11 @@
- (NSString*) name; - (NSString*) name;
- (id) obj; - (id) obj;
- (void) ping; - (void) ping;
- (int) processIdentifier;
- (void) setConfig: (NSData*)c; - (void) setConfig: (NSData*)c;
- (void) setName: (NSString*)n; - (void) setName: (NSString*)n;
- (void) setObj: (id)o; - (void) setObj: (id)o;
- (void) setProcessIdentifier: (int)p;
- (void) setTransient: (BOOL)flag; - (void) setTransient: (BOOL)flag;
- (void) setUnregistered: (BOOL)flag; - (void) setUnregistered: (BOOL)flag;
- (BOOL) transient; - (BOOL) transient;

View file

@ -164,6 +164,11 @@
} }
} }
- (int) processIdentifier
{
return processIdentifier;
}
- (void) setConfig: (NSData*)c - (void) setConfig: (NSData*)c
{ {
ASSIGN(config, c); ASSIGN(config, c);
@ -179,6 +184,11 @@
ASSIGN(obj, o); ASSIGN(obj, o);
} }
- (void) setProcessIdentifier: (int)p
{
processIdentifier = p;
}
- (void) setTransient: (BOOL)flag - (void) setTransient: (BOOL)flag
{ {
transient = flag ? YES : NO; transient = flag ? YES : NO;

View file

@ -129,7 +129,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
NSArray *launchOrder; NSArray *launchOrder;
NSDictionary *environment; NSDictionary *environment;
NSMutableDictionary *launches; NSMutableDictionary *launches;
NSMutableSet *launching; NSMutableDictionary *launching;
unsigned pingPosition; unsigned pingPosition;
NSTimer *terminating; NSTimer *terminating;
NSDate *lastUnanswered; NSDate *lastUnanswered;
@ -171,6 +171,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
from: (NSString*)s from: (NSString*)s
to: (NSString*)d to: (NSString*)d
type: (EcLogType)t; type: (EcLogType)t;
- (void) killAll;
- (void) launch; - (void) launch;
- (void) logMessage: (NSString*)msg - (void) logMessage: (NSString*)msg
type: (EcLogType)t type: (EcLogType)t
@ -1776,7 +1777,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
host = RETAIN([[NSHost currentHost] wellKnownName]); host = RETAIN([[NSHost currentHost] wellKnownName]);
clients = [[NSMutableArray alloc] initWithCapacity: 10]; clients = [[NSMutableArray alloc] initWithCapacity: 10];
launches = [[NSMutableDictionary alloc] initWithCapacity: 10]; launches = [[NSMutableDictionary alloc] initWithCapacity: 10];
launching = [[NSMutableSet alloc] initWithCapacity: 10]; launching = [[NSMutableDictionary alloc] initWithCapacity: 10];
timer = [NSTimer scheduledTimerWithTimeInterval: 5.0 timer = [NSTimer scheduledTimerWithTimeInterval: 5.0
target: self target: self
@ -1788,6 +1789,32 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
return self; return self;
} }
- (void) killAll
{
#ifndef __MINGW__
NSUInteger i = [clients count];
if (i > 0)
{
while (i-- > 0)
{
EcClientI *c;
c = [clients objectAtIndex: i];
if (nil != c)
{
int p = [c processIdentifier];
if (p > 0)
{
kill(p, SIGKILL);
}
}
}
}
#endif
}
- (void) launch - (void) launch
{ {
if (launchInfo != nil) if (launchInfo != nil)
@ -1857,6 +1884,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
NSDictionary *addE = [taskInfo objectForKey: @"AddE"]; NSDictionary *addE = [taskInfo objectForKey: @"AddE"];
NSDictionary *setE = [taskInfo objectForKey: @"SetE"]; NSDictionary *setE = [taskInfo objectForKey: @"SetE"];
NSString *failed = nil; NSString *failed = nil;
NSTask *task = nil;
NSString *m; NSString *m;
/* As a convenience, the 'Home' option sets the -HomeDirectory /* As a convenience, the 'Home' option sets the -HomeDirectory
@ -1878,11 +1906,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
/* Record time of launch start and the fact that this is launching. /* Record time of launch start and the fact that this is launching.
*/ */
[launches setObject: now forKey: key]; [launches setObject: now forKey: key];
if (nil == [launching member: key]) if (nil != [launching objectForKey: key])
{
[launching addObject: key];
}
else
{ {
NSString *managedObject; NSString *managedObject;
EcAlarm *a; EcAlarm *a;
@ -1901,10 +1925,12 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
additionalText: @"failed to register after launch"]; additionalText: @"failed to register after launch"];
[self alarm: a]; [self alarm: a];
} }
task = [NSTask new];
[launching setObject: task forKey: key];
RELEASE(task);
if (prog != nil && [prog length] > 0) if (prog != nil && [prog length] > 0)
{ {
NSTask *task;
NSFileHandle *hdl; NSFileHandle *hdl;
if (setE != nil) if (setE != nil)
@ -1922,7 +1948,6 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
[e addEntriesFromDictionary: addE]; [e addEntriesFromDictionary: addE];
env = AUTORELEASE(e); env = AUTORELEASE(e);
} }
task = [NSTask new];
[task setEnvironment: env]; [task setEnvironment: env];
hdl = [NSFileHandle fileHandleWithNullDevice]; hdl = [NSFileHandle fileHandleWithNullDevice];
NS_DURING NS_DURING
@ -1963,7 +1988,6 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
[self information: m from: nil to: nil type: LT_AUDIT]; [self information: m from: nil to: nil type: LT_AUDIT];
} }
NS_ENDHANDLER NS_ENDHANDLER
RELEASE(task);
} }
else else
{ {
@ -2063,8 +2087,8 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
if ([clients count] > 0) if ([clients count] > 0)
{ {
unsigned i; NSUInteger i;
unsigned j; NSUInteger j;
NSMutableArray *a; NSMutableArray *a;
/* Now we tell all connected clients to quit. /* Now we tell all connected clients to quit.
@ -2202,10 +2226,12 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
RELEASE(obj); RELEASE(obj);
[clients sortUsingSelector: @selector(compare:)]; [clients sortUsingSelector: @selector(compare:)];
[obj setProcessIdentifier: [c processIdentifier]];
/* This client has launched ... remove it from the set of launching /* This client has launched ... remove it from the set of launching
* clients. * clients.
*/ */
[launching removeObject: n]; [launching removeObjectForKey: n];
/* /*
* If this client is in the list of launchable clients, set * If this client is in the list of launchable clients, set
@ -2294,7 +2320,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
NSDate *when; NSDate *when;
/* We tell all connected clients to quit. /* We tell all connected clients to quit ... allow at most 30 seconds.
*/ */
a = [[clients mutableCopy] autorelease]; a = [[clients mutableCopy] autorelease];
i = [a count]; i = [a count];
@ -2616,7 +2642,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
*/ */
- (void) terminate: (NSTimer*)t - (void) terminate: (NSTimer*)t
{ {
if (terminating == nil) if (nil == terminating)
{ {
[self information: @"Handling shutdown." [self information: @"Handling shutdown."
from: nil from: nil
@ -2638,12 +2664,13 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
{ {
NSDate *when = (NSDate*)[t userInfo]; NSDate *when = (NSDate*)[t userInfo];
if ([when timeIntervalSinceNow] < -60.0) if ([when timeIntervalSinceNow] < -30.0)
{ {
[[self cmdLogFile: logname] [[self cmdLogFile: logname]
puts: @"Final shutdown.\n"]; puts: @"Final shutdown.\n"];
[terminating invalidate]; [terminating invalidate];
terminating = nil; terminating = nil;
[self killAll];
[self cmdQuit: tStatus]; [self cmdQuit: tStatus];
} }
} }

View file

@ -2169,7 +2169,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
} }
} }
- (void) requestConfigFor: (id<CmdConfig>)c - (oneway void) requestConfigFor: (id<CmdConfig>)c
{ {
return; return;
} }

View file

@ -231,6 +231,7 @@ typedef enum {
@protocol CmdClient <CmdPing,CmdConfig> @protocol CmdClient <CmdPing,CmdConfig>
- (oneway void) cmdMesgData: (in bycopy NSData*)dat from: (NSString*)name; - (oneway void) cmdMesgData: (in bycopy NSData*)dat from: (NSString*)name;
- (oneway void) cmdQuit: (NSInteger)status; - (oneway void) cmdQuit: (NSInteger)status;
- (int) processIdentifier;
@end @end
/** Messages a Command logging process can be expected to handle. /** Messages a Command logging process can be expected to handle.
@ -268,7 +269,10 @@ typedef enum {
- (oneway void) reply: (NSString*)msg - (oneway void) reply: (NSString*)msg
to: (NSString*)n to: (NSString*)n
from: (NSString*)c; from: (NSString*)c;
/** Shut down the Command server and all its clients */ /** Shut down the Command server and all its clients.<br />
* Clients which fail to shut down gracefully within 30 seconds
* make be killed.
*/
- (oneway void) terminate; - (oneway void) terminate;
/** This is an exceptional method which may be used without registering /** This is an exceptional method which may be used without registering
@ -951,6 +955,10 @@ extern NSString* cmdVersion(NSString *ver);
- (void) cmdMesgnodebug: (NSArray*)msg; - (void) cmdMesgnodebug: (NSArray*)msg;
- (void) cmdMesgstatus: (NSArray*)msg; - (void) cmdMesgstatus: (NSArray*)msg;
/** Returns the system process identifier for the client process.
*/
- (int) processIdentifier;
/** /**
* Returns a proxy object to a[n automatically managed] server process.<br /> * Returns a proxy object to a[n automatically managed] server process.<br />
* The serverName must previously have been registered using the * The serverName must previously have been registered using the

View file

@ -1032,11 +1032,13 @@ findMode(NSDictionary* d, NSString* s)
+ (NSMutableDictionary*) ecInitialDefaults + (NSMutableDictionary*) ecInitialDefaults
{ {
NSProcessInfo *pi;
id objects[2]; id objects[2];
id keys[2]; id keys[2];
NSString *prefix; NSString *prefix;
objects[0] = [[NSProcessInfo processInfo] processName]; pi = [NSProcessInfo processInfo];
objects[0] = [pi processName];
objects[1] = @"."; objects[1] = @".";
prefix = EC_DEFAULTS_PREFIX; prefix = EC_DEFAULTS_PREFIX;
if (nil == prefix) if (nil == prefix)
@ -1623,6 +1625,17 @@ static NSString *noFiles = @"No log files to archive";
[alarmDestination unmanage: managedObject]; [alarmDestination unmanage: managedObject];
} }
- (int) processIdentifier
{
static int pi = 0;
if (0 == pi)
{
pi = [[NSProcessInfo processInfo] processIdentifier];
}
return pi;
}
- (void) setCmdInterval: (NSTimeInterval)interval - (void) setCmdInterval: (NSTimeInterval)interval
{ {
if (interval > 60.0) if (interval > 60.0)
@ -2620,9 +2633,9 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
} }
} }
- (void) cmdGnip: (id <CmdPing>)from - (oneway void) cmdGnip: (id <CmdPing>)from
sequence: (unsigned)num sequence: (unsigned)num
extra: (NSData*)data extra: (in bycopy NSData*)data
{ {
[self cmdDbg: cmdConnectDbg msg: @"cmdGnip: %lx sequence: %u extra: %lx", [self cmdDbg: cmdConnectDbg msg: @"cmdGnip: %lx sequence: %u extra: %lx",
(unsigned long)from, num, (unsigned long)data]; (unsigned long)from, num, (unsigned long)data];
@ -3386,9 +3399,9 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
} }
- (void) cmdPing: (id <CmdPing>)from - (oneway void) cmdPing: (id <CmdPing>)from
sequence: (unsigned)num sequence: (unsigned)num
extra: (NSData*)data extra: (in bycopy NSData*)data
{ {
[self cmdDbg: cmdConnectDbg msg: @"cmdPing: %lx sequence: %u extra: %lx", [self cmdDbg: cmdConnectDbg msg: @"cmdPing: %lx sequence: %u extra: %lx",
(unsigned long)from, num, (unsigned long)data]; (unsigned long)from, num, (unsigned long)data];
@ -4057,7 +4070,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
format: @"Illegal method call"]; format: @"Illegal method call"];
} }
- (void) requestConfigFor: (id<CmdConfig>)c - (oneway void) requestConfigFor: (id<CmdConfig>)c
{ {
[NSException raise: NSGenericException [NSException raise: NSGenericException
format: @"Illegal method call"]; format: @"Illegal method call"];
@ -4071,7 +4084,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
format: @"Illegal method call"]; format: @"Illegal method call"];
} }
- (void) updateConfig: (NSData*)info - (oneway void) updateConfig: (in bycopy NSData*)info
{ {
id plist = [NSPropertyListSerialization id plist = [NSPropertyListSerialization
propertyListWithData: info propertyListWithData: info

View file

@ -48,7 +48,7 @@ LIBRARIES_DEPEND_UPON += $(ECCL_LIBS)
# Extras for when building with SNMP support # Extras for when building with SNMP support
# #
ifeq ($(WITH_NET_SNMP),yes) ifeq ($(WITH_NET_SNMP),yes)
EcAlarmSinkSNMP.m_FILE_FLAGS += $(shell net-snmp-config --cflags | sed -e 's/-l[^ ]*//g' | sed -e 's/-fstack-protect-strong//g') EcAlarmSinkSNMP.m_FILE_FLAGS += $(shell net-snmp-config --cflags | sed -e 's/-l[^ ]*//g' | sed -e 's/-fstack-protector-strong//g')
LIBRARIES_DEPEND_UPON += $(shell net-snmp-config --agent-libs) LIBRARIES_DEPEND_UPON += $(shell net-snmp-config --agent-libs)
endif endif