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>
* GNUmakefile.preamble: Fix wrong option letter in sed command.

View file

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

View file

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

View file

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

View file

@ -231,6 +231,7 @@ typedef enum {
@protocol CmdClient <CmdPing,CmdConfig>
- (oneway void) cmdMesgData: (in bycopy NSData*)dat from: (NSString*)name;
- (oneway void) cmdQuit: (NSInteger)status;
- (int) processIdentifier;
@end
/** Messages a Command logging process can be expected to handle.
@ -268,7 +269,10 @@ typedef enum {
- (oneway void) reply: (NSString*)msg
to: (NSString*)n
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;
/** 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) 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 />
* The serverName must previously have been registered using the

View file

@ -1032,11 +1032,13 @@ findMode(NSDictionary* d, NSString* s)
+ (NSMutableDictionary*) ecInitialDefaults
{
NSProcessInfo *pi;
id objects[2];
id keys[2];
NSString *prefix;
objects[0] = [[NSProcessInfo processInfo] processName];
pi = [NSProcessInfo processInfo];
objects[0] = [pi processName];
objects[1] = @".";
prefix = EC_DEFAULTS_PREFIX;
if (nil == prefix)
@ -1623,6 +1625,17 @@ static NSString *noFiles = @"No log files to archive";
[alarmDestination unmanage: managedObject];
}
- (int) processIdentifier
{
static int pi = 0;
if (0 == pi)
{
pi = [[NSProcessInfo processInfo] processIdentifier];
}
return pi;
}
- (void) setCmdInterval: (NSTimeInterval)interval
{
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
sequence: (unsigned)num
extra: (NSData*)data
- (oneway void) cmdGnip: (id <CmdPing>)from
sequence: (unsigned)num
extra: (in bycopy NSData*)data
{
[self cmdDbg: cmdConnectDbg msg: @"cmdGnip: %lx sequence: %u extra: %lx",
(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
sequence: (unsigned)num
extra: (NSData*)data
- (oneway void) cmdPing: (id <CmdPing>)from
sequence: (unsigned)num
extra: (in bycopy NSData*)data
{
[self cmdDbg: cmdConnectDbg msg: @"cmdPing: %lx sequence: %u extra: %lx",
(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"];
}
- (void) requestConfigFor: (id<CmdConfig>)c
- (oneway void) requestConfigFor: (id<CmdConfig>)c
{
[NSException raise: NSGenericException
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"];
}
- (void) updateConfig: (NSData*)info
- (oneway void) updateConfig: (in bycopy NSData*)info
{
id plist = [NSPropertyListSerialization
propertyListWithData: info

View file

@ -48,7 +48,7 @@ LIBRARIES_DEPEND_UPON += $(ECCL_LIBS)
# Extras for when building with SNMP support
#
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)
endif