Fix NSURLSession memory management of libdispatch objects and overrelease in GSHTTPURLProtocol.

This commit is contained in:
Frederik Seiffert 2023-01-13 12:48:22 +01:00 committed by Frederik Seiffert
parent 2f5b26df06
commit 18f81f9ccc
7 changed files with 51 additions and 13 deletions

View file

@ -1,3 +1,14 @@
2023-01-13 Frederik Seiffert <frederik@algoriddim.com>
* Source/GSEasyHandle.m:
* Source/GSMultiHandle.m:
* Source/GSTimeoutSource.h:
* Source/GSTimeoutSource.m:
* Source/NSURLSession.m:
Fix NSURLSession memory management of libdispatch objects.
* Source/GSHTTPURLProtocol.m:
Fix overrelease.
2023-01-13 Frederik Seiffert <frederik@algoriddim.com>
* Headers/Foundation/NSURLSession.h:

View file

@ -195,6 +195,7 @@ curl_socket_function(void *userdata, curl_socket_t fd, curlsocktype type)
curl_slist_free_all(_headerList);
free(_errorBuffer);
DESTROY(_config);
[_timeoutTimer cancel];
DESTROY(_timeoutTimer);
DESTROY(_URL);
[super dealloc];
@ -217,6 +218,7 @@ curl_socket_function(void *userdata, curl_socket_t fd, curlsocktype type)
- (void) setTimeoutTimer: (GSTimeoutSource*)timer
{
[_timeoutTimer cancel];
ASSIGN(_timeoutTimer, timer);
}
@ -234,10 +236,15 @@ curl_socket_function(void *userdata, curl_socket_t fd, curlsocktype type)
{
// simply create a new timer with the same queue, timeout and handler
// this must cancel the old handler and reset the timer
DESTROY(_timeoutTimer);
_timeoutTimer = [[GSTimeoutSource alloc] initWithQueue: [_timeoutTimer queue]
milliseconds: [_timeoutTimer milliseconds]
handler: [_timeoutTimer handler]];
if (_timeoutTimer)
{
GSTimeoutSource *oldTimer = _timeoutTimer;
[oldTimer cancel];
_timeoutTimer = [[GSTimeoutSource alloc] initWithQueue: [oldTimer queue]
milliseconds: [oldTimer milliseconds]
handler: [oldTimer handler]];
RELEASE(oldTimer);
}
}
- (void) setupCallbacks

View file

@ -592,17 +592,14 @@ parseArgumentPart(NSString *part, NSString *name)
[hh addEntriesFromDictionary:
[self transformLowercaseKeyForHTTPHeaders: HTTPHeaders]];
NSArray *curlHeaders = [self curlHeadersForHTTPHeaders: hh];
NSMutableArray *curlHeaders = [self curlHeadersForHTTPHeaders: hh];
if ([[request HTTPMethod] isEqualToString:@"POST"]
&& [[request HTTPBody] length] > 0
&& [request valueForHTTPHeaderField: @"Content-Type"] == nil)
{
NSMutableArray *temp = [curlHeaders mutableCopy];
[temp addObject: @"Content-Type:application/x-www-form-urlencoded"];
curlHeaders = temp;
[curlHeaders addObject: @"Content-Type:application/x-www-form-urlencoded"];
}
[_easyHandle setCustomHeaders: curlHeaders];
RELEASE(curlHeaders);
NSInteger timeoutInterval = [request timeoutInterval] * 1000;
GSTimeoutSource *timeoutTimer;
@ -874,7 +871,7 @@ parseArgumentPart(NSString *part, NSString *name)
// expects.
//
// - SeeAlso: https://curl.haxx.se/libcurl/c/CURLOPT_HTTPHEADER.html
- (NSArray*) curlHeadersForHTTPHeaders: (NSDictionary*)HTTPHeaders
- (NSMutableArray*) curlHeadersForHTTPHeaders: (NSDictionary*)HTTPHeaders
{
NSMutableArray *result = [NSMutableArray array];
NSMutableSet *names = [NSMutableSet set];
@ -951,7 +948,7 @@ parseArgumentPart(NSString *part, NSString *name)
[result addObject: [NSString stringWithFormat: @"%@:", k]];
}
return AUTORELEASE([result copy]);
return result;
}
// Any header values that should be passed to libcurl

View file

@ -108,8 +108,11 @@ static int curl_timer_function(CURL *easyHandle, int timeout, void *userdata) {
NSEnumerator *e;
GSEasyHandle *handle;
[_timeoutSource cancel];
DESTROY(_timeoutSource);
dispatch_release(_queue);
e = [_easyHandles objectEnumerator];
while (nil != (handle = [e nextObject]))
{
@ -193,10 +196,12 @@ static int curl_timer_function(CURL *easyHandle, int timeout, void *userdata) {
// of milliseconds.
if (-1 == value)
{
[_timeoutSource cancel];
DESTROY(_timeoutSource);
}
else if (0 == value)
{
[_timeoutSource cancel];
DESTROY(_timeoutSource);
dispatch_async(_queue,
^{
@ -207,6 +212,7 @@ static int curl_timer_function(CURL *easyHandle, int timeout, void *userdata) {
{
if (nil == _timeoutSource || value != [_timeoutSource milliseconds])
{
[_timeoutSource cancel];
DESTROY(_timeoutSource);
_timeoutSource = [[GSTimeoutSource alloc] initWithQueue: _queue
milliseconds: value
@ -438,12 +444,14 @@ static int curl_timer_function(CURL *easyHandle, int timeout, void *userdata) {
if (_readSource)
{
dispatch_source_cancel(_readSource);
dispatch_release(_readSource);
}
_readSource = NULL;
if (_writeSource)
{
dispatch_source_cancel(_writeSource);
dispatch_release(_writeSource);
}
_writeSource = NULL;
[super dealloc];

View file

@ -17,6 +17,8 @@
dispatch_block_t _handler;
}
- (void) cancel;
- (NSInteger) milliseconds;
- (dispatch_queue_t) queue;

View file

@ -9,7 +9,7 @@
if (nil != (self = [super init]))
{
_queue = queue;
_handler = handler;
_handler = Block_copy(handler);
_milliseconds = milliseconds;
_rawSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _queue);
@ -26,10 +26,21 @@
- (void) dealloc
{
dispatch_source_cancel(_rawSource);
[self cancel];
Block_release(_handler);
[super dealloc];
}
- (void) cancel
{
if (_rawSource)
{
dispatch_source_cancel(_rawSource);
dispatch_release(_rawSource);
_rawSource = NULL;
}
}
- (NSInteger) milliseconds
{
return _milliseconds;

View file

@ -970,6 +970,7 @@ static int nextSessionIdentifier()
DESTROY(_protocolBag);
DESTROY(_dataCompletionHandler);
DESTROY(_knownBody);
dispatch_release(_workQueue);
[super dealloc];
}
@ -1212,6 +1213,7 @@ static int nextSessionIdentifier()
copy->_state = _state;
copy->_error = [_error copyWithZone: zone];
copy->_session = _session;
dispatch_retain(_workQueue);
copy->_workQueue = _workQueue;
copy->_suspendCount = _suspendCount;
copy->_protocolLock = [_protocolLock copy];