diff --git a/Headers/GNUstepBase/NSObject+GNUstepBase.h b/Headers/GNUstepBase/NSObject+GNUstepBase.h
index cc4ccda05..bef4a5c74 100644
--- a/Headers/GNUstepBase/NSObject+GNUstepBase.h
+++ b/Headers/GNUstepBase/NSObject+GNUstepBase.h
@@ -219,10 +219,10 @@ extern "C" {
* set to YES).
* Your class then has two options for performing clean-up when the process
* ends:
- *
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 clean-up setting in force. This mechanism is simple - * and should be sufficient for many classes. + *
1. Use the +leaked: method to register addresses whose contents are to + * be either ignored or released depending on the clean-up setting in force + * when the program exits. + * 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 @@ -241,10 +241,11 @@ extern "C" { */ + (BOOL) isExiting; -/** 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. +/** This method informs the system that anAddress is a pointer whose content + * has been leaked and should be released and zeroed out (if clean-up is + * enabled) at process exit. If the content of the location is changed + * between the point where this method is called and the process exits, + * then the new content of the address is what will be released on clean-up. */ + (void) leaked: (id*)anAddress; diff --git a/Source/Additions/NSObject+GNUstepBase.m b/Source/Additions/NSObject+GNUstepBase.m index 6b14eed96..d2c1c757b 100644 --- a/Source/Additions/NSObject+GNUstepBase.m +++ b/Source/Additions/NSObject+GNUstepBase.m @@ -181,7 +181,7 @@ handleExit() isExiting = YES; unknownThread = GSRegisterCurrentThread(); - CREATE_AUTORELEASE_POOL(arp); + ENTER_POOL while (exited != 0) { @@ -202,7 +202,7 @@ handleExit() } else if (YES == shouldCleanUp) { - if (0 != tmp->at) + if (tmp->at) { tmp->obj = *(tmp->at); *(tmp->at) = nil; @@ -211,7 +211,8 @@ handleExit() } free(tmp); } - DESTROY(arp); + LEAVE_POOL + if (unknownThread == YES) { GSUnregisterCurrentThread(); diff --git a/Source/GSTLS.m b/Source/GSTLS.m index 24ec20eee..b1a1f5867 100644 --- a/Source/GSTLS.m +++ b/Source/GSTLS.m @@ -188,9 +188,22 @@ static gnutls_anon_client_credentials_t anoncred; */ @implementation GSTLSObject +static NSLock *certificateListLock = nil; +static NSMutableDictionary *certificateListCache = nil; + +static NSLock *credentialsLock = nil; +static NSMutableDictionary *credentialsCache = nil; + static NSLock *fileLock = nil; static NSMutableDictionary *fileMap = nil; +static NSLock *paramsLock = nil; +static NSMutableDictionary *paramsCache = nil; + +static NSLock *privateKeyLock = nil; +static NSMutableDictionary *privateKeyCache0 = nil; +static NSMutableDictionary *privateKeyCache1 = nil; + + (void) _defaultsChanged: (NSNotification*)n { NSBundle *bundle; @@ -289,6 +302,21 @@ static NSMutableDictionary *fileMap = nil; gnutls_global_set_log_level(globalDebug); } ++ (void) atExit +{ + DESTROY(certificateListLock); + DESTROY(certificateListCache); + DESTROY(credentialsLock); + DESTROY(credentialsCache); + DESTROY(fileLock); + DESTROY(fileMap); + DESTROY(paramsLock); + DESTROY(paramsCache); + DESTROY(privateKeyLock); + DESTROY(privateKeyCache0); + DESTROY(privateKeyCache1); +} + + (NSData*) dataForTLSFile: (NSString*)fileName { NSData *result; @@ -328,6 +356,8 @@ static NSMutableDictionary *fileMap = nil; { beenHere = YES; + [self registerAtExit]; + fileLock = [NSLock new]; fileMap = [NSMutableDictionary new]; @@ -397,8 +427,6 @@ static NSMutableDictionary *fileMap = nil; @end @implementation GSTLSDHParams -static NSLock *paramsLock = nil; -static NSMutableDictionary *paramsCache = nil; static NSTimeInterval paramsWhen = 0.0; static BOOL paramsGenerating = NO; static GSTLSDHParams *paramsCurrent = nil; @@ -496,10 +524,8 @@ static GSTLSDHParams *paramsCurrent = nil; if (nil == paramsLock) { paramsLock = [NSLock new]; - [[NSObject leakAt: ¶msLock] release]; paramsWhen = [NSDate timeIntervalSinceReferenceDate]; paramsCache = [NSMutableDictionary new]; - [[NSObject leakAt: ¶msCache] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) name: @"GSHousekeeping" object: nil]; @@ -570,8 +596,6 @@ static GSTLSDHParams *paramsCurrent = nil; @implementation GSTLSCertificateList -static NSLock *certificateListLock = nil; -static NSMutableDictionary *certificateListCache = nil; + (void) certInfo: (gnutls_x509_crt_t)cert to: (NSMutableString*)str { @@ -700,9 +724,7 @@ static NSMutableDictionary *certificateListCache = nil; if (nil == certificateListLock) { certificateListLock = [NSLock new]; - [[NSObject leakAt: &certificateListLock] release]; certificateListCache = [NSMutableDictionary new]; - [[NSObject leakAt: &certificateListCache] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) name: @"GSHousekeeping" object: nil]; @@ -884,9 +906,6 @@ static NSMutableDictionary *certificateListCache = nil; @implementation GSTLSPrivateKey -static NSLock *privateKeyLock = nil; -static NSMutableDictionary *privateKeyCache0 = nil; -static NSMutableDictionary *privateKeyCache1 = nil; /* Method to purge older keys from cache. */ @@ -940,11 +959,8 @@ static NSMutableDictionary *privateKeyCache1 = nil; if (nil == privateKeyLock) { privateKeyLock = [NSLock new]; - [[NSObject leakAt: &privateKeyLock] release]; privateKeyCache0 = [NSMutableDictionary new]; - [[NSObject leakAt: &privateKeyCache0] release]; privateKeyCache1 = [NSMutableDictionary new]; - [[NSObject leakAt: &privateKeyCache1] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) @@ -1074,8 +1090,6 @@ static NSMutableDictionary *privateKeyCache1 = nil; @implementation GSTLSCredentials -static NSLock *credentialsLock = nil; -static NSMutableDictionary *credentialsCache = nil; /* Method to purge older credentials from cache. */ @@ -1106,9 +1120,7 @@ static NSMutableDictionary *credentialsCache = nil; if (nil == credentialsLock) { credentialsLock = [NSLock new]; - [[NSObject leakAt: &credentialsLock] release]; credentialsCache = [NSMutableDictionary new]; - [[NSObject leakAt: &credentialsCache] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(housekeeping:) diff --git a/Source/NSCharacterSet.m b/Source/NSCharacterSet.m index 5363887a4..cacd8c810 100644 --- a/Source/NSCharacterSet.m +++ b/Source/NSCharacterSet.m @@ -632,6 +632,15 @@ static Class concreteMutableClass = nil; return abstractClass; } +- (void) dealloc +{ + if (cache_map[_index] == self) + { + cache_map[_index] = nil; + } + [super dealloc]; +} + - (void) encodeWithCoder: (NSCoder*)aCoder { [aCoder encodeValueOfObjCType: @encode(int) at: &_index]; @@ -707,6 +716,20 @@ static Class concreteMutableClass = nil; @implementation NSCharacterSet +static gs_mutex_t cache_lock = GS_MUTEX_INIT_STATIC; + ++ (void) atExit +{ + unsigned i; + + for (i = 0; i < MAX_STANDARD_SETS; i++) + { + GS_MUTEX_LOCK(cache_lock); + DESTROY(cache_set[i]); + GS_MUTEX_UNLOCK(cache_lock); + } +} + + (void) initialize { static BOOL beenHere = NO; @@ -723,6 +746,7 @@ static Class concreteMutableClass = nil; concreteMutableClass = [NSMutableBitmapCharSet class]; #endif beenHere = YES; + [self registerAtExit]; } } @@ -735,7 +759,7 @@ static Class concreteMutableClass = nil; length: (unsigned)length number: (int)number { - static gs_mutex_t cache_lock = GS_MUTEX_INIT_STATIC; + NSCharacterSet *set; GS_MUTEX_LOCK(cache_lock); if (cache_set[number] == nil && bytes != 0) @@ -747,11 +771,11 @@ static Class concreteMutableClass = nil; freeWhenDone: NO]; cache_set[number] = [[_GSStaticCharSet alloc] initWithBitmap: bitmap number: number]; - [[NSObject leakAt: &cache_set[number]] release]; RELEASE(bitmap); } + set = RETAIN(cache_set[number]); GS_MUTEX_UNLOCK(cache_lock); - return cache_set[number]; + return AUTORELEASE(set); } + (id) alphanumericCharacterSet diff --git a/Source/NSTimeZone.m b/Source/NSTimeZone.m index 3f478c775..1768fbb60 100644 --- a/Source/NSTimeZone.m +++ b/Source/NSTimeZone.m @@ -643,7 +643,6 @@ static NSMapTable *absolutes = 0; { absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, NSNonOwnedPointerMapValueCallBacks, 0); - [[NSObject leakAt: (id*)&absolutes] release]; } } @@ -1281,6 +1280,24 @@ static NSMapTable *absolutes = 0; } } ++ (void) atExit +{ + id o; + + DESTROY(zoneDictionary); + DESTROY(placeholderMap); + DESTROY(localTimeZone); + DESTROY(defaultTimeZone); + DESTROY(systemTimeZone); + DESTROY(abbreviationDictionary); + DESTROY(abbreviationMap); + DESTROY(absolutes); + + o = defaultPlaceholderTimeZone; + defaultPlaceholderTimeZone = nil; + NSDeallocateObject(o); +} + /** * Return the default time zone for this process. */ @@ -1309,31 +1326,23 @@ static NSMapTable *absolutes = 0; GS_MUTEX_INIT_RECURSIVE(zone_mutex); GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class]; zoneDictionary = [[NSMutableDictionary alloc] init]; - [[NSObject leakAt: &zoneDictionary] release]; /* * Set up infrastructure for placeholder timezones. */ defaultPlaceholderTimeZone = (GSPlaceholderTimeZone*) NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone()); - [[NSObject leakAt: &defaultPlaceholderTimeZone] release]; placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, NSNonRetainedObjectMapValueCallBacks, 0); - [[NSObject leakAt: (id*)&placeholderMap] release]; localTimeZone = [[NSLocalTimeZone alloc] init]; - [[NSObject leakAt: (id*)&localTimeZone] release]; - - [[NSObject leakAt: (id*)&defaultTimeZone] release]; - [[NSObject leakAt: (id*)&systemTimeZone] release]; - [[NSObject leakAt: (id*)&abbreviationDictionary] release]; - [[NSObject leakAt: (id*)&abbreviationMap] release]; - [[NSObject leakAt: (id*)&absolutes] release]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(_notified:) name: NSUserDefaultsDidChangeNotification object: nil]; + + [self registerAtExit]; } }