mirror of
https://github.com/gnustep/libs-ec.git
synced 2025-02-22 11:21:28 +00:00
Fix bug in archiving and simplify code
This commit is contained in:
parent
b4c1c3c320
commit
291b295089
5 changed files with 173 additions and 186 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2017-06-23 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* EcCommand.m:
|
||||||
|
* EcControl.m:
|
||||||
|
* EcProcess.h:
|
||||||
|
* EcProcess.m:
|
||||||
|
Replace cmdArchive: with ecArchive: changing trhe log file archiving
|
||||||
|
model to archive files primarily based on their last modification
|
||||||
|
date. Fixes the bug where files were archived to a folder with the
|
||||||
|
wrong datre on startup, and simplifies archiving code generally.
|
||||||
|
|
||||||
2017-03-06 Richard Frith-Macdonald <rfm@gnu.org>
|
2017-03-06 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* EcAlarmDestination.h:
|
* EcAlarmDestination.h:
|
||||||
|
|
11
EcCommand.m
11
EcCommand.m
|
@ -752,16 +752,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
|
||||||
}
|
}
|
||||||
else if (comp(wd, @"archive") >= 0)
|
else if (comp(wd, @"archive") >= 0)
|
||||||
{
|
{
|
||||||
NSCalendarDate *when = [NSCalendarDate date];
|
m = [NSString stringWithFormat: @"\n%@\n\n", [self ecArchive: nil]];
|
||||||
NSString *sub;
|
|
||||||
int yy, mm, dd;
|
|
||||||
|
|
||||||
yy = [when yearOfCommonEra];
|
|
||||||
mm = [when monthOfYear];
|
|
||||||
dd = [when dayOfMonth];
|
|
||||||
|
|
||||||
sub = [NSString stringWithFormat: @"%04d-%02d-%02d", yy, mm, dd];
|
|
||||||
m = [NSString stringWithFormat: @"\n%@\n\n", [self cmdArchive: sub]];
|
|
||||||
}
|
}
|
||||||
else if (comp(wd, @"help") >= 0)
|
else if (comp(wd, @"help") >= 0)
|
||||||
{
|
{
|
||||||
|
|
11
EcControl.m
11
EcControl.m
|
@ -798,16 +798,7 @@ static NSString* cmdWord(NSArray* a, unsigned int pos)
|
||||||
}
|
}
|
||||||
else if (comp(wd, @"archive") >= 0)
|
else if (comp(wd, @"archive") >= 0)
|
||||||
{
|
{
|
||||||
NSCalendarDate *when = [NSCalendarDate date];
|
m = [NSString stringWithFormat: @"\n%@\n\n", [self ecArchive: nil]];
|
||||||
NSString *sub;
|
|
||||||
int yy, mm, dd;
|
|
||||||
|
|
||||||
yy = [when yearOfCommonEra];
|
|
||||||
mm = [when monthOfYear];
|
|
||||||
dd = [when dayOfMonth];
|
|
||||||
|
|
||||||
sub = [NSString stringWithFormat: @"%04d-%02d-%02d", yy, mm, dd];
|
|
||||||
m = [NSString stringWithFormat: @"\n%@\n\n", [self cmdArchive: sub]];
|
|
||||||
}
|
}
|
||||||
else if (comp(wd, @"clear") >= 0)
|
else if (comp(wd, @"clear") >= 0)
|
||||||
{
|
{
|
||||||
|
|
28
EcProcess.h
28
EcProcess.h
|
@ -570,12 +570,12 @@ extern NSString* cmdVersion(NSString *ver);
|
||||||
*/
|
*/
|
||||||
- (void) cmdAlert: (NSString*)fmt, ... NS_FORMAT_FUNCTION(1,2);
|
- (void) cmdAlert: (NSString*)fmt, ... NS_FORMAT_FUNCTION(1,2);
|
||||||
|
|
||||||
/** Archives debug log files into the specified subdirectory of the debug
|
/** Archives debug log files into the appropriate subdirectory for the
|
||||||
* logging directory. If subdir is nil then a subdirectory name corresponding
|
* supplied date (or the files last modification date if when is nil).<br />
|
||||||
* to the current date is generated and that subdirectory is created if
|
* Returns a text description of any archiving actually done.<br />
|
||||||
* necessary.
|
* The subdirectory is created if necessary.
|
||||||
*/
|
*/
|
||||||
- (NSString*) cmdArchive: (NSString*)subdir;
|
- (NSString*) ecArchive: (NSDate*)when;
|
||||||
|
|
||||||
/** Send a log message to the server.
|
/** Send a log message to the server.
|
||||||
*/
|
*/
|
||||||
|
@ -662,10 +662,12 @@ extern NSString* cmdVersion(NSString *ver);
|
||||||
*/
|
*/
|
||||||
- (BOOL) cmdIsTesting;
|
- (BOOL) cmdIsTesting;
|
||||||
|
|
||||||
/** Closes a file handle previously obtained using the -cmdLogFile: method.
|
/** Closes a file previously obtained using the -cmdLogFile: method.<br />
|
||||||
|
* Returns a description of any file archiving done, or nil if the file
|
||||||
|
* dis not exist.<br />
|
||||||
* You should not close a logging handle directly, use this method.
|
* You should not close a logging handle directly, use this method.
|
||||||
*/
|
*/
|
||||||
- (void) cmdLogEnd: (NSString*)name;
|
- (NSString*) cmdLogEnd: (NSString*)name;
|
||||||
|
|
||||||
/** Obtain a file handle for logging purposes. The file will have the
|
/** Obtain a file handle for logging purposes. The file will have the
|
||||||
* specified name and will be created (if necessary) in the processes
|
* specified name and will be created (if necessary) in the processes
|
||||||
|
@ -920,8 +922,10 @@ extern NSString* cmdVersion(NSString *ver);
|
||||||
* It's therefore recommended that you use 'lazy' initialisation of subclass
|
* It's therefore recommended that you use 'lazy' initialisation of subclass
|
||||||
* instance variables as/when they are needed, rather than initialising
|
* instance variables as/when they are needed, rather than initialising
|
||||||
* them in the -initWithDefaults: method.<br />
|
* them in the -initWithDefaults: method.<br />
|
||||||
* An alternative strategy is to perform subclass initialisaton before
|
* For a normal process, the recommended place to perform initialisation is
|
||||||
* calling the superclass implementation.
|
* immediately after initialisation (when configuration information has been
|
||||||
|
* retrieved from the Command server), typically by overriding the
|
||||||
|
* -ecRun method.
|
||||||
*/
|
*/
|
||||||
- (id) initWithDefaults: (NSDictionary*)defs;
|
- (id) initWithDefaults: (NSDictionary*)defs;
|
||||||
|
|
||||||
|
@ -1031,7 +1035,11 @@ extern NSString* cmdVersion(NSString *ver);
|
||||||
/** Establishes the receiver as a DO server and runs the runloop.<br />
|
/** Establishes the receiver as a DO server and runs the runloop.<br />
|
||||||
* Returns zero when the run loop completes.<br />
|
* Returns zero when the run loop completes.<br />
|
||||||
* Returns one (immediately) if the receiver is transent.<br />
|
* Returns one (immediately) if the receiver is transent.<br />
|
||||||
* Returns two if unable to register as a DO server.
|
* Returns two if unable to register as a DO server.<br />
|
||||||
|
* This is the recommended location to perform any initialisation of your
|
||||||
|
* subclass which needs configuration information from the Command server;
|
||||||
|
* override this method, perform your initialisation, and then call the
|
||||||
|
* superclass implementation of the method to enter the run loop.
|
||||||
*/
|
*/
|
||||||
- (int) ecRun;
|
- (int) ecRun;
|
||||||
|
|
||||||
|
|
148
EcProcess.m
148
EcProcess.m
|
@ -1038,7 +1038,7 @@ findMode(NSDictionary* d, NSString* s)
|
||||||
- (void) cmdMesgrelease: (NSArray*)msg;
|
- (void) cmdMesgrelease: (NSArray*)msg;
|
||||||
- (void) cmdMesgtesting: (NSArray*)msg;
|
- (void) cmdMesgtesting: (NSArray*)msg;
|
||||||
- (void) _memCheck;
|
- (void) _memCheck;
|
||||||
- (NSString*) _moveLog: (NSString*)name to: (NSString*)sub;
|
- (NSString*) _moveLog: (NSString*)name to: (NSDate*)when;
|
||||||
- (void) _timedOut: (NSTimer*)timer;
|
- (void) _timedOut: (NSTimer*)timer;
|
||||||
- (void) _update: (NSMutableDictionary*)info;
|
- (void) _update: (NSMutableDictionary*)info;
|
||||||
@end
|
@end
|
||||||
|
@ -1496,24 +1496,27 @@ static NSString *noFiles = @"No log files to archive";
|
||||||
return [dateClass dateWithTimeIntervalSinceReferenceDate: lastOP];
|
return [dateClass dateWithTimeIntervalSinceReferenceDate: lastOP];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) cmdLogEnd: (NSString*)name
|
- (NSString*) cmdLogEnd: (NSString*)name
|
||||||
{
|
{
|
||||||
NSFileHandle *hdl;
|
NSString *status = nil;
|
||||||
|
|
||||||
if ([name length] == 0)
|
if ([name length] == 0)
|
||||||
{
|
{
|
||||||
NSLog(@"Attempt to end log with empty filename");
|
NSLog(@"Attempt to end log with empty filename");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSFileHandle *hdl;
|
||||||
|
|
||||||
name = [name lastPathComponent];
|
name = [name lastPathComponent];
|
||||||
|
|
||||||
[self ecDoLock];
|
[self ecDoLock];
|
||||||
hdl = [cmdLogMap objectForKey: name];
|
hdl = [cmdLogMap objectForKey: name];
|
||||||
if (hdl != nil)
|
if (hdl != nil)
|
||||||
{
|
{
|
||||||
NSString *path;
|
/* If the file is empty, remove it, otherwise archive it.
|
||||||
NSDictionary *attr;
|
*/
|
||||||
NSFileManager *mgr;
|
status = [self _moveLog: name to: nil];
|
||||||
|
|
||||||
/* Ensure that all data is written to file, then close it unless it's
|
/* Ensure that all data is written to file, then close it unless it's
|
||||||
* stderr (which we must keep open for logging at all times).
|
* stderr (which we must keep open for logging at all times).
|
||||||
|
@ -1527,36 +1530,14 @@ static NSString *noFiles = @"No log files to archive";
|
||||||
NS_ENDHANDLER
|
NS_ENDHANDLER
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* If the file is empty, remove it, otherwise move to archive directory.
|
|
||||||
*/
|
|
||||||
path = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
|
|
||||||
mgr = [NSFileManager defaultManager];
|
|
||||||
attr = [mgr fileAttributesAtPath: path traverseLink: NO];
|
|
||||||
if ([[attr objectForKey: NSFileSize] intValue] == 0)
|
|
||||||
{
|
|
||||||
[mgr removeFileAtPath: path handler: nil];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
NSDate *when;
|
|
||||||
NSString *where;
|
|
||||||
|
|
||||||
when = [NSDate date];
|
|
||||||
where = [when descriptionWithCalendarFormat: @"%Y-%m-%d"
|
|
||||||
timeZone: nil locale: nil];
|
|
||||||
if (where != nil)
|
|
||||||
{
|
|
||||||
[self _moveLog: name to: where];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unregister filename.
|
* Unregister filename.
|
||||||
*/
|
*/
|
||||||
[cmdLogMap removeObjectForKey: name];
|
[cmdLogMap removeObjectForKey: name];
|
||||||
}
|
}
|
||||||
[self ecUnLock];
|
[self ecUnLock];
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSFileHandle*) cmdLogFile: (NSString*)name
|
- (NSFileHandle*) cmdLogFile: (NSString*)name
|
||||||
|
@ -1572,28 +1553,16 @@ static NSString *noFiles = @"No log files to archive";
|
||||||
name = [name lastPathComponent];
|
name = [name lastPathComponent];
|
||||||
[self ecDoLock];
|
[self ecDoLock];
|
||||||
hdl = [cmdLogMap objectForKey: name];
|
hdl = [cmdLogMap objectForKey: name];
|
||||||
if (hdl == nil)
|
if (nil == hdl)
|
||||||
{
|
{
|
||||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||||
NSString *path;
|
NSString *path;
|
||||||
|
|
||||||
path = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
|
path = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
|
||||||
|
|
||||||
if ([mgr fileExistsAtPath: path] == YES)
|
/* Archive any old left-over file.
|
||||||
{
|
*/
|
||||||
NSDictionary *attr;
|
[self _moveLog: name to: nil];
|
||||||
NSDate *when;
|
|
||||||
NSString *where;
|
|
||||||
|
|
||||||
attr = [mgr fileAttributesAtPath: path traverseLink: NO];
|
|
||||||
when = [attr objectForKey: NSFileModificationDate];
|
|
||||||
where = [when descriptionWithCalendarFormat: @"%Y-%m-%d"
|
|
||||||
timeZone: nil locale: nil];
|
|
||||||
if (where != nil)
|
|
||||||
{
|
|
||||||
status = [self _moveLog: name to: where];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create the file if necessary, and open it for updating.
|
* Create the file if necessary, and open it for updating.
|
||||||
|
@ -1941,7 +1910,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
||||||
va_end (ap);
|
va_end (ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*) cmdArchive: (NSString*)subdir
|
- (NSString*) ecArchive: (NSDate*)when
|
||||||
{
|
{
|
||||||
NSString *status = @"";
|
NSString *status = @"";
|
||||||
|
|
||||||
|
@ -1957,27 +1926,18 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
||||||
[self ecDoLock];
|
[self ecDoLock];
|
||||||
enumerator = [[cmdLogMap allKeys] objectEnumerator];
|
enumerator = [[cmdLogMap allKeys] objectEnumerator];
|
||||||
[self ecUnLock];
|
[self ecUnLock];
|
||||||
if (subdir == nil)
|
|
||||||
{
|
|
||||||
NSCalendarDate *when = [NSCalendarDate date];
|
|
||||||
int y, m, d;
|
|
||||||
|
|
||||||
y = [when yearOfCommonEra];
|
|
||||||
m = [when monthOfYear];
|
|
||||||
d = [when dayOfMonth];
|
|
||||||
|
|
||||||
subdir = [stringClass stringWithFormat: @"%04d-%02d-%02d", y, m, d];
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((name = [enumerator nextObject]) != nil)
|
while ((name = [enumerator nextObject]) != nil)
|
||||||
{
|
{
|
||||||
NSString *s;
|
NSString *s;
|
||||||
|
|
||||||
s = [self _moveLog: name to: subdir];
|
s = [self cmdLogEnd: name];
|
||||||
|
if (nil != s)
|
||||||
|
{
|
||||||
if ([status length] > 0)
|
if ([status length] > 0)
|
||||||
status = [status stringByAppendingString: @"\n"];
|
status = [status stringByAppendingString: @"\n"];
|
||||||
status = [status stringByAppendingString: s];
|
status = [status stringByAppendingString: s];
|
||||||
[self cmdLogEnd: name];
|
}
|
||||||
if (cmdIsQuitting == NO)
|
if (cmdIsQuitting == NO)
|
||||||
{
|
{
|
||||||
[self cmdLogFile: name];
|
[self cmdLogFile: name];
|
||||||
|
@ -2320,21 +2280,21 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
||||||
- (void) ecNewDay: (NSCalendarDate*)when
|
- (void) ecNewDay: (NSCalendarDate*)when
|
||||||
{
|
{
|
||||||
static NSDictionary *defs = nil;
|
static NSDictionary *defs = nil;
|
||||||
NSString *sub;
|
NSDictionary *d = [cmdDefs volatileDomainForName: @"EcCommand"];
|
||||||
NSDictionary *d;
|
|
||||||
|
if (nil != defs)
|
||||||
|
{
|
||||||
NSEnumerator *e;
|
NSEnumerator *e;
|
||||||
NSString *k;
|
NSString *k;
|
||||||
|
|
||||||
/* New day ... archive debug/log files into a subdirectory based on
|
/* Archive previous day's logs. Force logs to be archived for the
|
||||||
* the current date. This is yesterday's debug, so we use yesterday.
|
* specified date even if they have been modified today (on the basis
|
||||||
|
* that only the very latest info in them should be from today).
|
||||||
*/
|
*/
|
||||||
sub = [[when dateByAddingYears: 0 months: 0 days: -1 hours: 0 minutes: 0
|
NSLog(@"%@", [self ecArchive: when]);
|
||||||
seconds: 0] descriptionWithCalendarFormat: @"%Y-%m-%d"];
|
|
||||||
NSLog(@"%@", [self cmdArchive: sub]);
|
|
||||||
|
|
||||||
/* Check information left in the EcCommand domain.
|
/* Check information left in the EcCommand domain.
|
||||||
*/
|
*/
|
||||||
d = [cmdDefs volatileDomainForName: @"EcCommand"];
|
|
||||||
e = [[d allKeys] objectEnumerator];
|
e = [[d allKeys] objectEnumerator];
|
||||||
while (nil != (k = [e nextObject]))
|
while (nil != (k = [e nextObject]))
|
||||||
{
|
{
|
||||||
|
@ -2344,8 +2304,10 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
||||||
{
|
{
|
||||||
[self cmdError: @"The Console defaults override for '%@'"
|
[self cmdError: @"The Console defaults override for '%@'"
|
||||||
@" has been left at '%@' for more than a day."
|
@" has been left at '%@' for more than a day."
|
||||||
@" Please reset it ('tell %@ defaults delete %@') after updating"
|
@" Please reset it ('tell %@ defaults delete %@') after"
|
||||||
@" Control.plist as required.", k, v, [self cmdName], k];
|
@" updating Control.plist as required.",
|
||||||
|
k, v, [self cmdName], k];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ASSIGNCOPY(defs, d);
|
ASSIGNCOPY(defs, d);
|
||||||
|
@ -2855,7 +2817,7 @@ NSLog(@"Ignored attempt to set timer interval to %g ... using 10.0", interval);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
[self cmdPrintf: @"\n%@\n", [self cmdArchive: nil]];
|
[self cmdPrintf: @"\n%@\n", [self ecArchive: nil]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4309,7 +4271,7 @@ With two parameters ('maximum' and a number),\n\
|
||||||
/*
|
/*
|
||||||
* Force archiving of old logfile.
|
* Force archiving of old logfile.
|
||||||
*/
|
*/
|
||||||
[self cmdArchive: nil];
|
[self ecArchive: nil];
|
||||||
|
|
||||||
ASSIGNCOPY(cmdDebugName, str);
|
ASSIGNCOPY(cmdDebugName, str);
|
||||||
hdl = [self cmdLogFile: cmdDebugName];
|
hdl = [self cmdLogFile: cmdDebugName];
|
||||||
|
@ -4592,7 +4554,7 @@ With two parameters ('maximum' and a number),\n\
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)_ensureMemLogger
|
- (void) _ensureMemLogger
|
||||||
{
|
{
|
||||||
NSString *bundle = [cmdDefs stringForKey: @"MemoryLoggerBundle"];
|
NSString *bundle = [cmdDefs stringForKey: @"MemoryLoggerBundle"];
|
||||||
Class cls = Nil;
|
Class cls = Nil;
|
||||||
|
@ -4843,25 +4805,47 @@ With two parameters ('maximum' and a number),\n\
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*) _moveLog: (NSString*)name to: (NSString*)sub
|
- (NSString*) _moveLog: (NSString*)name to: (NSDate*)when
|
||||||
{
|
{
|
||||||
NSString *status;
|
NSString *status = nil;
|
||||||
NSString *where;
|
|
||||||
|
|
||||||
NS_DURING
|
NS_DURING
|
||||||
{
|
{
|
||||||
|
NSFileManager *mgr = [NSFileManager defaultManager];
|
||||||
|
NSString *from;
|
||||||
|
NSDictionary *attr;
|
||||||
|
|
||||||
|
from = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
|
||||||
|
attr = [mgr fileAttributesAtPath: from traverseLink: NO];
|
||||||
|
if (nil != attr)
|
||||||
|
{
|
||||||
|
if ([[attr objectForKey: NSFileSize] intValue] == 0)
|
||||||
|
{
|
||||||
|
[mgr removeFileAtPath: from handler: nil];
|
||||||
|
status = [NSString stringWithFormat:
|
||||||
|
@"Removed empty log %@", from];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSString *where;
|
||||||
|
NSString *sub;
|
||||||
|
|
||||||
|
if (nil == when)
|
||||||
|
{
|
||||||
|
when = [attr fileModificationDate];
|
||||||
|
}
|
||||||
|
sub = [when descriptionWithCalendarFormat: @"%Y-%m-%d"
|
||||||
|
timeZone: nil
|
||||||
|
locale: nil];
|
||||||
where = cmdLogsDir(sub);
|
where = cmdLogsDir(sub);
|
||||||
if (where != nil)
|
if (where != nil)
|
||||||
{
|
{
|
||||||
NSFileManager *mgr = [NSFileManager defaultManager];
|
|
||||||
NSString *from;
|
|
||||||
NSString *path;
|
NSString *path;
|
||||||
NSString *base;
|
NSString *base;
|
||||||
NSString *gzpath;
|
NSString *gzpath;
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
|
|
||||||
path = [where stringByAppendingPathComponent: name];
|
path = [where stringByAppendingPathComponent: name];
|
||||||
from = [cmdLogsDir(nil) stringByAppendingPathComponent: name];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for pre-existing file - if found, try another.
|
* Check for pre-existing file - if found, try another.
|
||||||
|
@ -4898,10 +4882,12 @@ With two parameters ('maximum' and a number),\n\
|
||||||
@"Unable to archive log %@ into %@", name, sub];
|
@"Unable to archive log %@ into %@", name, sub];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
NS_HANDLER
|
NS_HANDLER
|
||||||
{
|
{
|
||||||
status = [NSString stringWithFormat: @"Problem in %@ with %@ to %@ - %@",
|
status = [NSString stringWithFormat: @"Problem in %@ with %@ to %@ - %@",
|
||||||
NSStringFromSelector(_cmd), name, sub, localException];
|
NSStringFromSelector(_cmd), name, when, localException];
|
||||||
}
|
}
|
||||||
NS_ENDHANDLER
|
NS_ENDHANDLER
|
||||||
return status;
|
return status;
|
||||||
|
|
Loading…
Reference in a new issue