Some more leak improvements

This commit is contained in:
rfm 2024-11-14 14:45:05 +00:00
parent dd3367de3b
commit 25505b2e67
5 changed files with 90 additions and 43 deletions

View file

@ -219,10 +219,10 @@ extern "C" {
* set to YES).<br /> * set to YES).<br />
* Your class then has two options for performing clean-up when the process * Your class then has two options for performing clean-up when the process
* ends: * ends:
* <p>1. Use the +leaked: method to register objects which are simply to be * <p>1. Use the +leaked: method to register addresses whose contents are to
* retained until the process ends, and then either ignored or released * be either ignored or released depending on the clean-up setting in force
* depending on the clean-up setting in force. This mechanism is simple * when the program exits.
* and should be sufficient for many classes. * This mechanism is simple and should be sufficient for many classes.
* </p> * </p>
* <p>2. Implement a +atExit method to be run when the process ends and, * <p>2. Implement a +atExit method to be run when the process ends and,
* within your +initialize implementation, call +shouldCleanUp to determine * within your +initialize implementation, call +shouldCleanUp to determine
@ -241,10 +241,11 @@ extern "C" {
*/ */
+ (BOOL) isExiting; + (BOOL) isExiting;
/** This method informs the system that the object at anAddress has been /** This method informs the system that anAddress is a pointer whose content
* intentionally leaked (will not be deallocated by higher level code) * has been leaked and should be released and zeroed out (if clean-up is
* and should be cleaned up at process exit (and the address content * enabled) at process exit. If the content of the location is changed
* zeroed out) if clean-up is enabled. * 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; + (void) leaked: (id*)anAddress;

View file

@ -181,7 +181,7 @@ handleExit()
isExiting = YES; isExiting = YES;
unknownThread = GSRegisterCurrentThread(); unknownThread = GSRegisterCurrentThread();
CREATE_AUTORELEASE_POOL(arp); ENTER_POOL
while (exited != 0) while (exited != 0)
{ {
@ -202,7 +202,7 @@ handleExit()
} }
else if (YES == shouldCleanUp) else if (YES == shouldCleanUp)
{ {
if (0 != tmp->at) if (tmp->at)
{ {
tmp->obj = *(tmp->at); tmp->obj = *(tmp->at);
*(tmp->at) = nil; *(tmp->at) = nil;
@ -211,7 +211,8 @@ handleExit()
} }
free(tmp); free(tmp);
} }
DESTROY(arp); LEAVE_POOL
if (unknownThread == YES) if (unknownThread == YES)
{ {
GSUnregisterCurrentThread(); GSUnregisterCurrentThread();

View file

@ -188,9 +188,22 @@ static gnutls_anon_client_credentials_t anoncred;
*/ */
@implementation GSTLSObject @implementation GSTLSObject
static NSLock *certificateListLock = nil;
static NSMutableDictionary *certificateListCache = nil;
static NSLock *credentialsLock = nil;
static NSMutableDictionary *credentialsCache = nil;
static NSLock *fileLock = nil; static NSLock *fileLock = nil;
static NSMutableDictionary *fileMap = 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 + (void) _defaultsChanged: (NSNotification*)n
{ {
NSBundle *bundle; NSBundle *bundle;
@ -289,6 +302,21 @@ static NSMutableDictionary *fileMap = nil;
gnutls_global_set_log_level(globalDebug); 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*) dataForTLSFile: (NSString*)fileName
{ {
NSData *result; NSData *result;
@ -328,6 +356,8 @@ static NSMutableDictionary *fileMap = nil;
{ {
beenHere = YES; beenHere = YES;
[self registerAtExit];
fileLock = [NSLock new]; fileLock = [NSLock new];
fileMap = [NSMutableDictionary new]; fileMap = [NSMutableDictionary new];
@ -397,8 +427,6 @@ static NSMutableDictionary *fileMap = nil;
@end @end
@implementation GSTLSDHParams @implementation GSTLSDHParams
static NSLock *paramsLock = nil;
static NSMutableDictionary *paramsCache = nil;
static NSTimeInterval paramsWhen = 0.0; static NSTimeInterval paramsWhen = 0.0;
static BOOL paramsGenerating = NO; static BOOL paramsGenerating = NO;
static GSTLSDHParams *paramsCurrent = nil; static GSTLSDHParams *paramsCurrent = nil;
@ -496,10 +524,8 @@ static GSTLSDHParams *paramsCurrent = nil;
if (nil == paramsLock) if (nil == paramsLock)
{ {
paramsLock = [NSLock new]; paramsLock = [NSLock new];
[[NSObject leakAt: &paramsLock] release];
paramsWhen = [NSDate timeIntervalSinceReferenceDate]; paramsWhen = [NSDate timeIntervalSinceReferenceDate];
paramsCache = [NSMutableDictionary new]; paramsCache = [NSMutableDictionary new];
[[NSObject leakAt: &paramsCache] release];
[[NSNotificationCenter defaultCenter] addObserver: self [[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(housekeeping:) selector: @selector(housekeeping:)
name: @"GSHousekeeping" object: nil]; name: @"GSHousekeeping" object: nil];
@ -570,8 +596,6 @@ static GSTLSDHParams *paramsCurrent = nil;
@implementation GSTLSCertificateList @implementation GSTLSCertificateList
static NSLock *certificateListLock = nil;
static NSMutableDictionary *certificateListCache = nil;
+ (void) certInfo: (gnutls_x509_crt_t)cert to: (NSMutableString*)str + (void) certInfo: (gnutls_x509_crt_t)cert to: (NSMutableString*)str
{ {
@ -700,9 +724,7 @@ static NSMutableDictionary *certificateListCache = nil;
if (nil == certificateListLock) if (nil == certificateListLock)
{ {
certificateListLock = [NSLock new]; certificateListLock = [NSLock new];
[[NSObject leakAt: &certificateListLock] release];
certificateListCache = [NSMutableDictionary new]; certificateListCache = [NSMutableDictionary new];
[[NSObject leakAt: &certificateListCache] release];
[[NSNotificationCenter defaultCenter] addObserver: self [[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(housekeeping:) selector: @selector(housekeeping:)
name: @"GSHousekeeping" object: nil]; name: @"GSHousekeeping" object: nil];
@ -884,9 +906,6 @@ static NSMutableDictionary *certificateListCache = nil;
@implementation GSTLSPrivateKey @implementation GSTLSPrivateKey
static NSLock *privateKeyLock = nil;
static NSMutableDictionary *privateKeyCache0 = nil;
static NSMutableDictionary *privateKeyCache1 = nil;
/* Method to purge older keys from cache. /* Method to purge older keys from cache.
*/ */
@ -940,11 +959,8 @@ static NSMutableDictionary *privateKeyCache1 = nil;
if (nil == privateKeyLock) if (nil == privateKeyLock)
{ {
privateKeyLock = [NSLock new]; privateKeyLock = [NSLock new];
[[NSObject leakAt: &privateKeyLock] release];
privateKeyCache0 = [NSMutableDictionary new]; privateKeyCache0 = [NSMutableDictionary new];
[[NSObject leakAt: &privateKeyCache0] release];
privateKeyCache1 = [NSMutableDictionary new]; privateKeyCache1 = [NSMutableDictionary new];
[[NSObject leakAt: &privateKeyCache1] release];
[[NSNotificationCenter defaultCenter] addObserver: self [[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(housekeeping:) selector: @selector(housekeeping:)
@ -1074,8 +1090,6 @@ static NSMutableDictionary *privateKeyCache1 = nil;
@implementation GSTLSCredentials @implementation GSTLSCredentials
static NSLock *credentialsLock = nil;
static NSMutableDictionary *credentialsCache = nil;
/* Method to purge older credentials from cache. /* Method to purge older credentials from cache.
*/ */
@ -1106,9 +1120,7 @@ static NSMutableDictionary *credentialsCache = nil;
if (nil == credentialsLock) if (nil == credentialsLock)
{ {
credentialsLock = [NSLock new]; credentialsLock = [NSLock new];
[[NSObject leakAt: &credentialsLock] release];
credentialsCache = [NSMutableDictionary new]; credentialsCache = [NSMutableDictionary new];
[[NSObject leakAt: &credentialsCache] release];
[[NSNotificationCenter defaultCenter] addObserver: self [[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(housekeeping:) selector: @selector(housekeeping:)

View file

@ -632,6 +632,15 @@ static Class concreteMutableClass = nil;
return abstractClass; return abstractClass;
} }
- (void) dealloc
{
if (cache_map[_index] == self)
{
cache_map[_index] = nil;
}
[super dealloc];
}
- (void) encodeWithCoder: (NSCoder*)aCoder - (void) encodeWithCoder: (NSCoder*)aCoder
{ {
[aCoder encodeValueOfObjCType: @encode(int) at: &_index]; [aCoder encodeValueOfObjCType: @encode(int) at: &_index];
@ -707,6 +716,20 @@ static Class concreteMutableClass = nil;
@implementation NSCharacterSet @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 + (void) initialize
{ {
static BOOL beenHere = NO; static BOOL beenHere = NO;
@ -723,6 +746,7 @@ static Class concreteMutableClass = nil;
concreteMutableClass = [NSMutableBitmapCharSet class]; concreteMutableClass = [NSMutableBitmapCharSet class];
#endif #endif
beenHere = YES; beenHere = YES;
[self registerAtExit];
} }
} }
@ -735,7 +759,7 @@ static Class concreteMutableClass = nil;
length: (unsigned)length length: (unsigned)length
number: (int)number number: (int)number
{ {
static gs_mutex_t cache_lock = GS_MUTEX_INIT_STATIC; NSCharacterSet *set;
GS_MUTEX_LOCK(cache_lock); GS_MUTEX_LOCK(cache_lock);
if (cache_set[number] == nil && bytes != 0) if (cache_set[number] == nil && bytes != 0)
@ -747,11 +771,11 @@ static Class concreteMutableClass = nil;
freeWhenDone: NO]; freeWhenDone: NO];
cache_set[number] cache_set[number]
= [[_GSStaticCharSet alloc] initWithBitmap: bitmap number: number]; = [[_GSStaticCharSet alloc] initWithBitmap: bitmap number: number];
[[NSObject leakAt: &cache_set[number]] release];
RELEASE(bitmap); RELEASE(bitmap);
} }
set = RETAIN(cache_set[number]);
GS_MUTEX_UNLOCK(cache_lock); GS_MUTEX_UNLOCK(cache_lock);
return cache_set[number]; return AUTORELEASE(set);
} }
+ (id) alphanumericCharacterSet + (id) alphanumericCharacterSet

View file

@ -643,7 +643,6 @@ static NSMapTable *absolutes = 0;
{ {
absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks, absolutes = NSCreateMapTable(NSIntegerMapKeyCallBacks,
NSNonOwnedPointerMapValueCallBacks, 0); 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. * Return the default time zone for this process.
*/ */
@ -1309,31 +1326,23 @@ static NSMapTable *absolutes = 0;
GS_MUTEX_INIT_RECURSIVE(zone_mutex); GS_MUTEX_INIT_RECURSIVE(zone_mutex);
GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class]; GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class];
zoneDictionary = [[NSMutableDictionary alloc] init]; zoneDictionary = [[NSMutableDictionary alloc] init];
[[NSObject leakAt: &zoneDictionary] release];
/* /*
* Set up infrastructure for placeholder timezones. * Set up infrastructure for placeholder timezones.
*/ */
defaultPlaceholderTimeZone = (GSPlaceholderTimeZone*) defaultPlaceholderTimeZone = (GSPlaceholderTimeZone*)
NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone()); NSAllocateObject(GSPlaceholderTimeZoneClass, 0, NSDefaultMallocZone());
[[NSObject leakAt: &defaultPlaceholderTimeZone] release];
placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks, placeholderMap = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
NSNonRetainedObjectMapValueCallBacks, 0); NSNonRetainedObjectMapValueCallBacks, 0);
[[NSObject leakAt: (id*)&placeholderMap] release];
localTimeZone = [[NSLocalTimeZone alloc] init]; 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 [[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(_notified:) selector: @selector(_notified:)
name: NSUserDefaultsDidChangeNotification name: NSUserDefaultsDidChangeNotification
object: nil]; object: nil];
[self registerAtExit];
} }
} }