diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h
index 7c70ff988..cc4ccda05 100644
--- a/Headers/GNUstepBase/NSObject+GNUstepBase.h
+++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h
@@ -212,46 +212,49 @@ extern "C" {
+ (void) atExit;
@end
-/** Category for methods handling leaked memory cleanup on exit of process
+/** Category for methods handling leaked memory clean-up on exit of process
* (for use when debugging memory leaks).
* You enable this by calling the +setShouldCleanUp: method (done implicitly
* by gnustep-base if the GNUSTEP_SHOULD_CLEAN_UP environment variable is
* set to YES).
- * Your class then has two options for performing cleanup when the process
+ * Your class then has two options for performing clean-up when the process
* ends:
- *
1. Use the +leak: method to register objects which are simply to be
+ *
1. Use the +leaked: method to register objects which are simply to be
* retained until the process ends, and then either ignored or released
- * depending on the cleanup setting in force. This mechanism is simple
+ * depending on the clean-up setting in force. This mechanism is simple
* and should be sufficient for many classes.
*
* 2. Implement a +atExit method to be run when the process ends and,
* within your +initialize implementation, call +shouldCleanUp to determine
- * whether cleanup should be done, and if it returns YES then call
+ * whether clean-up should be done, and if it returns YES then call
* +registerAtExit to have your +atExit method called when the process
* terminates.
*
* The order in which 'leaked' objects are released and +atExit methods
* are called on process exist is the reverse of the order in which they
- * werse set up suing this API.
+ * werse set up using this API.
*
*/
-@interface NSObject(GSCleanup)
+@interface NSObject(GSCleanUp)
-
-/** This method simply retains its argument so that it will never be
- * deallocated during normal operation, but keeps track of it so that
- * it is released during process exit if cleanup is enabled.
- * Returns its argument.
+/** Returns YES if the process is exiting (and perhaps performing clean-up).
*/
-+ (id) NS_RETURNS_RETAINED leak: (id)anObject;
++ (BOOL) isExiting;
-/** This method retains the object at *anAddress so that it will never be
- * deallocated during normal operation, but keeps track of the address
- * so that the object is released and the address is zeroed during process
- * exit if cleanup is enabled.
- * Returns the object at *anAddress.
+/** This method informs the system that the object at anAddress has been
+ * intentionally leaked (will not be deallocated by higher level code)
+ * and should be cleaned up at process exit (and the address content
+ * zeroed out) if clean-up is enabled.
*/
-+ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress;
++ (void) leaked: (id*)anAddress;
+
+/** Deprecated: use +leaked: instead.
+ */
++ (id) NS_RETURNS_RETAINED leak: (id)anObject ;//GS_DEPRECATED_FUNC;
+
+/** Deprecated: use +leaked: instead.
+ */
++ (id) NS_RETURNS_RETAINED leakAt: (id*)anAddress ;//GS_DEPRECATED_FUNC;
/** Sets the receiver to have its +atExit method called at the point when
* the process terminates.
@@ -269,10 +272,10 @@ extern "C" {
*/
+ (BOOL) registerAtExit: (SEL)aSelector;
-/** Specifies the default cleanup behavior on process exit ... the value
+/** Specifies the default clean-up behavior on process exit ... the value
* returned by the NSObject implementation of the +shouldCleanUp method.
* Calling this method with a YES argument implicitly enables the support for
- * cleanup at exit.
+ * clean-up at exit.
* The GNUstep Base library calls this method with the value obtained from
* the GNUSTEP_SHOULD_CLEAN_UP environment variable when NSObject is
* initialised.
diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m
index 4818693d9..6b14eed96 100644
--- a/Source/Additions/NSObject+GNUstepBase.m
+++ b/Source/Additions/NSObject+GNUstepBase.m
@@ -156,6 +156,7 @@ struct exitLink {
static struct exitLink *exited = 0;
static BOOL enabled = NO;
static BOOL shouldCleanUp = NO;
+static BOOL isExiting = NO;
static NSLock *exitLock = nil;
static inline void setup()
@@ -176,7 +177,10 @@ static inline void setup()
static void
handleExit()
{
- BOOL unknownThread = GSRegisterCurrentThread();
+ BOOL unknownThread;
+
+ isExiting = YES;
+ unknownThread = GSRegisterCurrentThread();
CREATE_AUTORELEASE_POOL(arp);
while (exited != 0)
@@ -212,9 +216,32 @@ handleExit()
{
GSUnregisterCurrentThread();
}
+ isExiting = NO;
}
-@implementation NSObject(GSCleanup)
+@implementation NSObject(GSCleanUp)
+
++ (BOOL) isExiting
+{
+ return isExiting;
+}
+
++ (void) leaked: (id*)anAddress
+{
+ struct exitLink *l;
+
+ NSAssert(*anAddress && [*anAddress isKindOfClass: [NSObject class]],
+ NSInvalidArgumentException);
+ l = (struct exitLink*)malloc(sizeof(struct exitLink));
+ l->at = anAddress;
+ l->obj = *anAddress;
+ l->sel = 0;
+ setup();
+ [exitLock lock];
+ l->next = exited;
+ exited = l;
+ [exitLock unlock];
+}
+ (id) leakAt: (id*)anAddress
{
diff --git a/Source/NSArray.m b/Source/NSArray.m
index ea966e873..828c739b5 100644
--- a/Source/NSArray.m
+++ b/Source/NSArray.m
@@ -105,7 +105,15 @@ static SEL rlSel;
+ (void) atExit
{
- DESTROY(defaultPlaceholderArray);
+ id o;
+
+ /* The default placeholder array overrides -dealloc so we must get rid of
+ * it directly.
+ */
+ o = defaultPlaceholderArray;
+ defaultPlaceholderArray = nil;
+ NSDeallocateObject(o);
+
DESTROY(placeholderMap);
}
diff --git a/Source/NSString.m b/Source/NSString.m
index d73985ee3..91077a9dd 100644
--- a/Source/NSString.m
+++ b/Source/NSString.m
@@ -166,9 +166,13 @@ static NSMapTable *placeholderMap;
static gs_mutex_t placeholderLock = GS_MUTEX_INIT_STATIC;
-static SEL cMemberSel = 0;
-static NSCharacterSet *nonBase = nil;
-static BOOL (*nonBaseImp)(id, SEL, unichar) = 0;
+static SEL cMemberSel = 0;
+static NSCharacterSet *nonBase = nil;
+static BOOL (*nonBaseImp)(id, SEL, unichar) = 0;
+
+static NSCharacterSet *wPathSeps = nil;
+static NSCharacterSet *uPathSeps = nil;
+static NSCharacterSet *rPathSeps = nil;
/* Macro to return the receiver if it is already immutable, but an
* autoreleased copy otherwise. Used where we have to return an
@@ -308,9 +312,6 @@ GSPathHandling(const char *mode)
static NSCharacterSet*
pathSeps(void)
{
- static NSCharacterSet *wPathSeps = nil;
- static NSCharacterSet *uPathSeps = nil;
- static NSCharacterSet *rPathSeps = nil;
if (GSPathHandlingRight())
{
if (rPathSeps == nil)
@@ -318,9 +319,8 @@ pathSeps(void)
GS_MUTEX_LOCK(placeholderLock);
if (rPathSeps == nil)
{
- rPathSeps
- = [NSCharacterSet characterSetWithCharactersInString: @"/\\"];
- rPathSeps = [NSObject leakAt: &rPathSeps];
+ rPathSeps = RETAIN([NSCharacterSet
+ characterSetWithCharactersInString: @"/\\"]);
}
GS_MUTEX_UNLOCK(placeholderLock);
}
@@ -333,9 +333,8 @@ pathSeps(void)
GS_MUTEX_LOCK(placeholderLock);
if (uPathSeps == nil)
{
- uPathSeps
- = [NSCharacterSet characterSetWithCharactersInString: @"/"];
- uPathSeps = [NSObject leakAt: &uPathSeps];
+ uPathSeps = RETAIN([NSCharacterSet
+ characterSetWithCharactersInString: @"/"]);
}
GS_MUTEX_UNLOCK(placeholderLock);
}
@@ -348,9 +347,8 @@ pathSeps(void)
GS_MUTEX_LOCK(placeholderLock);
if (wPathSeps == nil)
{
- wPathSeps
- = [NSCharacterSet characterSetWithCharactersInString: @"\\"];
- wPathSeps = [NSObject leakAt: &wPathSeps];
+ wPathSeps = RETAIN([NSCharacterSet
+ characterSetWithCharactersInString: @"\\"]);
}
GS_MUTEX_UNLOCK(placeholderLock);
}
@@ -881,6 +879,10 @@ register_printf_atsign ()
+ (void) atExit
{
DESTROY(placeholderMap);
+ DESTROY(nonBase);
+ DESTROY(rPathSeps);
+ DESTROY(uPathSeps);
+ DESTROY(wPathSeps);
}
+ (void) initialize
@@ -900,7 +902,6 @@ register_printf_atsign ()
ranSel = @selector(rangeOfComposedCharacterSequenceAtIndex:);
nonBase = [NSCharacterSet nonBaseCharacterSet];
- nonBase = [NSObject leakAt: &nonBase];
nonBaseImp
= (BOOL(*)(id,SEL,unichar))[nonBase methodForSelector: cMemberSel];
@@ -3951,9 +3952,13 @@ register_printf_atsign ()
}
else
{
+ BOOL result;
+
+ ENTER_POOL
NSData *d = [self dataUsingEncoding: encoding];
unsigned length = [d length];
- BOOL result = (length < maxLength) ? YES : NO;
+
+ result = (length < maxLength) ? YES : NO;
if (d == nil)
{
@@ -3966,6 +3971,7 @@ register_printf_atsign ()
}
memcpy(buffer, [d bytes], length);
buffer[length] = '\0';
+ LEAVE_POOL
return result;
}
}
@@ -4279,7 +4285,7 @@ register_printf_atsign ()
if (GSFromUnicode(&b, &l, u, len, encoding, NSDefaultMallocZone(),
options) == YES)
{
- d = [NSDataClass dataWithBytesNoCopy: b length: l];
+ d = [NSDataClass dataWithBytesNoCopy: b length: l freeWhenDone: YES];
}
else
{