Leak when calling CFNetworkExecuteProxyAutoConfigurationURL on Mac










1















I am using CFNetwork APIs to detect OS proxy settings. My setup is heavily based on this:
https://github.com/adobe/chromium/blob/master/net/proxy/proxy_resolver_mac.cc
which is pretty much the same as this:
https://developer.apple.com/library/archive/samplecode/CFProxySupportTool/Introduction/Intro.html



I use CFNetworkCopyProxiesForURL to get the list of proxies, and for the PAC types, use CFNetworkExecuteProxyAutoConfigurationURL to fetch and execute the PAC script, immediately running the run loop on the current thread, which is already not on the ui thread.



This all works properly, and I have carefully combed through making sure that I am following the create rule to properly release results. However, when using Xcode instruments, I'm seeing that std::shared_ptrs to PAC::PACClient are leaked by _CFNetworkExecuteProxyAutoConfigurationURLDelegated. Since that object is never exposed to me, I'm not sure how I can control its release, but it is leaking. This is only an issue with fetching PAC files, explicit proxies do not leak. I have tried adding redundant CFRelease calls on all the CFDictionaries and such exposed to me to see if something was being over retained, but it didn't make a difference to the PACClient leak.



This is on Mac in a cpp file, not objective C, in a project with ARC on.



Has anyone encountered this leak and know how to prevent it?



Below is the snippet that executes the lookup, which is all the same steps from the above projects.



struct PACRequestInfo 
CFURLRef url; // Caller gets this from a dictionary, doesn't need release
CFURLRef scriptURL; // Caller gets this from a dictionary, doesn't need release
CFMutableArrayRef proxies; // Reference to a dictionary that is released by the caller
;

void resultCallback(void* client, CFArrayRef proxies, CFErrorRef error)
// Error handling removed for brevity
if (CFTypeRef* resultPtr = (CFTypeRef*) client)
*resultPtr = CFRetain(proxies);

CFRunLoopStop(CFRunLoopGetCurrent());


// Provided PACRequestInfo is created on the stack by the caller
void doPACRequest(const PACRequestInfo& info)
CFTypeRef result = nullptr;
CFStreamClientContext context = 0, &result, nullptr, nullptr, nullptr ;
// Scoped ptr not shown but just calls CFRelease on destruction
CFScopedPtr<CFRunLoopSourceRef> runLoopSource(CFNetworkExecuteProxyAutoConfigurationURL(info.scriptURL, info.url, resultCallback, &context));
if (runLoopSource)
const static CFStringRef kPrivateRunLoopMode = CFSTR("myprivateloop");
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);
CFRunLoopRunInMode(kPrivateRunLoopMode, 1.0e10, false);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);

if (result && CFGetTypeID(result) == CFArrayGetTypeID())
CFArrayRef resultArray = (CFArrayRef) result;
CFArrayAppendArray(info.proxies, resultArray, CFRangeMake(0, CFArrayGetCount(resultArray)));



// Retain was called on this value during ResultCallback.
if (result)
CFRelease(result);











share|improve this question






















  • Seems like a lot of stuff leaking in CFNetwork. I have SocketStream, and here's another proxy-related issue.

    – Sergei Ousynin
    Jan 8 at 19:01















1















I am using CFNetwork APIs to detect OS proxy settings. My setup is heavily based on this:
https://github.com/adobe/chromium/blob/master/net/proxy/proxy_resolver_mac.cc
which is pretty much the same as this:
https://developer.apple.com/library/archive/samplecode/CFProxySupportTool/Introduction/Intro.html



I use CFNetworkCopyProxiesForURL to get the list of proxies, and for the PAC types, use CFNetworkExecuteProxyAutoConfigurationURL to fetch and execute the PAC script, immediately running the run loop on the current thread, which is already not on the ui thread.



This all works properly, and I have carefully combed through making sure that I am following the create rule to properly release results. However, when using Xcode instruments, I'm seeing that std::shared_ptrs to PAC::PACClient are leaked by _CFNetworkExecuteProxyAutoConfigurationURLDelegated. Since that object is never exposed to me, I'm not sure how I can control its release, but it is leaking. This is only an issue with fetching PAC files, explicit proxies do not leak. I have tried adding redundant CFRelease calls on all the CFDictionaries and such exposed to me to see if something was being over retained, but it didn't make a difference to the PACClient leak.



This is on Mac in a cpp file, not objective C, in a project with ARC on.



Has anyone encountered this leak and know how to prevent it?



Below is the snippet that executes the lookup, which is all the same steps from the above projects.



struct PACRequestInfo 
CFURLRef url; // Caller gets this from a dictionary, doesn't need release
CFURLRef scriptURL; // Caller gets this from a dictionary, doesn't need release
CFMutableArrayRef proxies; // Reference to a dictionary that is released by the caller
;

void resultCallback(void* client, CFArrayRef proxies, CFErrorRef error)
// Error handling removed for brevity
if (CFTypeRef* resultPtr = (CFTypeRef*) client)
*resultPtr = CFRetain(proxies);

CFRunLoopStop(CFRunLoopGetCurrent());


// Provided PACRequestInfo is created on the stack by the caller
void doPACRequest(const PACRequestInfo& info)
CFTypeRef result = nullptr;
CFStreamClientContext context = 0, &result, nullptr, nullptr, nullptr ;
// Scoped ptr not shown but just calls CFRelease on destruction
CFScopedPtr<CFRunLoopSourceRef> runLoopSource(CFNetworkExecuteProxyAutoConfigurationURL(info.scriptURL, info.url, resultCallback, &context));
if (runLoopSource)
const static CFStringRef kPrivateRunLoopMode = CFSTR("myprivateloop");
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);
CFRunLoopRunInMode(kPrivateRunLoopMode, 1.0e10, false);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);

if (result && CFGetTypeID(result) == CFArrayGetTypeID())
CFArrayRef resultArray = (CFArrayRef) result;
CFArrayAppendArray(info.proxies, resultArray, CFRangeMake(0, CFArrayGetCount(resultArray)));



// Retain was called on this value during ResultCallback.
if (result)
CFRelease(result);











share|improve this question






















  • Seems like a lot of stuff leaking in CFNetwork. I have SocketStream, and here's another proxy-related issue.

    – Sergei Ousynin
    Jan 8 at 19:01













1












1








1


1






I am using CFNetwork APIs to detect OS proxy settings. My setup is heavily based on this:
https://github.com/adobe/chromium/blob/master/net/proxy/proxy_resolver_mac.cc
which is pretty much the same as this:
https://developer.apple.com/library/archive/samplecode/CFProxySupportTool/Introduction/Intro.html



I use CFNetworkCopyProxiesForURL to get the list of proxies, and for the PAC types, use CFNetworkExecuteProxyAutoConfigurationURL to fetch and execute the PAC script, immediately running the run loop on the current thread, which is already not on the ui thread.



This all works properly, and I have carefully combed through making sure that I am following the create rule to properly release results. However, when using Xcode instruments, I'm seeing that std::shared_ptrs to PAC::PACClient are leaked by _CFNetworkExecuteProxyAutoConfigurationURLDelegated. Since that object is never exposed to me, I'm not sure how I can control its release, but it is leaking. This is only an issue with fetching PAC files, explicit proxies do not leak. I have tried adding redundant CFRelease calls on all the CFDictionaries and such exposed to me to see if something was being over retained, but it didn't make a difference to the PACClient leak.



This is on Mac in a cpp file, not objective C, in a project with ARC on.



Has anyone encountered this leak and know how to prevent it?



Below is the snippet that executes the lookup, which is all the same steps from the above projects.



struct PACRequestInfo 
CFURLRef url; // Caller gets this from a dictionary, doesn't need release
CFURLRef scriptURL; // Caller gets this from a dictionary, doesn't need release
CFMutableArrayRef proxies; // Reference to a dictionary that is released by the caller
;

void resultCallback(void* client, CFArrayRef proxies, CFErrorRef error)
// Error handling removed for brevity
if (CFTypeRef* resultPtr = (CFTypeRef*) client)
*resultPtr = CFRetain(proxies);

CFRunLoopStop(CFRunLoopGetCurrent());


// Provided PACRequestInfo is created on the stack by the caller
void doPACRequest(const PACRequestInfo& info)
CFTypeRef result = nullptr;
CFStreamClientContext context = 0, &result, nullptr, nullptr, nullptr ;
// Scoped ptr not shown but just calls CFRelease on destruction
CFScopedPtr<CFRunLoopSourceRef> runLoopSource(CFNetworkExecuteProxyAutoConfigurationURL(info.scriptURL, info.url, resultCallback, &context));
if (runLoopSource)
const static CFStringRef kPrivateRunLoopMode = CFSTR("myprivateloop");
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);
CFRunLoopRunInMode(kPrivateRunLoopMode, 1.0e10, false);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);

if (result && CFGetTypeID(result) == CFArrayGetTypeID())
CFArrayRef resultArray = (CFArrayRef) result;
CFArrayAppendArray(info.proxies, resultArray, CFRangeMake(0, CFArrayGetCount(resultArray)));



// Retain was called on this value during ResultCallback.
if (result)
CFRelease(result);











share|improve this question














I am using CFNetwork APIs to detect OS proxy settings. My setup is heavily based on this:
https://github.com/adobe/chromium/blob/master/net/proxy/proxy_resolver_mac.cc
which is pretty much the same as this:
https://developer.apple.com/library/archive/samplecode/CFProxySupportTool/Introduction/Intro.html



I use CFNetworkCopyProxiesForURL to get the list of proxies, and for the PAC types, use CFNetworkExecuteProxyAutoConfigurationURL to fetch and execute the PAC script, immediately running the run loop on the current thread, which is already not on the ui thread.



This all works properly, and I have carefully combed through making sure that I am following the create rule to properly release results. However, when using Xcode instruments, I'm seeing that std::shared_ptrs to PAC::PACClient are leaked by _CFNetworkExecuteProxyAutoConfigurationURLDelegated. Since that object is never exposed to me, I'm not sure how I can control its release, but it is leaking. This is only an issue with fetching PAC files, explicit proxies do not leak. I have tried adding redundant CFRelease calls on all the CFDictionaries and such exposed to me to see if something was being over retained, but it didn't make a difference to the PACClient leak.



This is on Mac in a cpp file, not objective C, in a project with ARC on.



Has anyone encountered this leak and know how to prevent it?



Below is the snippet that executes the lookup, which is all the same steps from the above projects.



struct PACRequestInfo 
CFURLRef url; // Caller gets this from a dictionary, doesn't need release
CFURLRef scriptURL; // Caller gets this from a dictionary, doesn't need release
CFMutableArrayRef proxies; // Reference to a dictionary that is released by the caller
;

void resultCallback(void* client, CFArrayRef proxies, CFErrorRef error)
// Error handling removed for brevity
if (CFTypeRef* resultPtr = (CFTypeRef*) client)
*resultPtr = CFRetain(proxies);

CFRunLoopStop(CFRunLoopGetCurrent());


// Provided PACRequestInfo is created on the stack by the caller
void doPACRequest(const PACRequestInfo& info)
CFTypeRef result = nullptr;
CFStreamClientContext context = 0, &result, nullptr, nullptr, nullptr ;
// Scoped ptr not shown but just calls CFRelease on destruction
CFScopedPtr<CFRunLoopSourceRef> runLoopSource(CFNetworkExecuteProxyAutoConfigurationURL(info.scriptURL, info.url, resultCallback, &context));
if (runLoopSource)
const static CFStringRef kPrivateRunLoopMode = CFSTR("myprivateloop");
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);
CFRunLoopRunInMode(kPrivateRunLoopMode, 1.0e10, false);
CFRunLoopRemoveSource(CFRunLoopGetCurrent(), runLoopSource, kPrivateRunLoopMode);

if (result && CFGetTypeID(result) == CFArrayGetTypeID())
CFArrayRef resultArray = (CFArrayRef) result;
CFArrayAppendArray(info.proxies, resultArray, CFRangeMake(0, CFArrayGetCount(resultArray)));



// Retain was called on this value during ResultCallback.
if (result)
CFRelease(result);








memory-leaks proxy cfnetwork cfrunloop






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 '18 at 23:10









ManeugeantManeugeant

63




63












  • Seems like a lot of stuff leaking in CFNetwork. I have SocketStream, and here's another proxy-related issue.

    – Sergei Ousynin
    Jan 8 at 19:01

















  • Seems like a lot of stuff leaking in CFNetwork. I have SocketStream, and here's another proxy-related issue.

    – Sergei Ousynin
    Jan 8 at 19:01
















Seems like a lot of stuff leaking in CFNetwork. I have SocketStream, and here's another proxy-related issue.

– Sergei Ousynin
Jan 8 at 19:01





Seems like a lot of stuff leaking in CFNetwork. I have SocketStream, and here's another proxy-related issue.

– Sergei Ousynin
Jan 8 at 19:01












0






active

oldest

votes











Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53290871%2fleak-when-calling-cfnetworkexecuteproxyautoconfigurationurl-on-mac%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























0






active

oldest

votes








0






active

oldest

votes









active

oldest

votes






active

oldest

votes















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53290871%2fleak-when-calling-cfnetworkexecuteproxyautoconfigurationurl-on-mac%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







這個網誌中的熱門文章

How to read a connectionString WITH PROVIDER in .NET Core?

Node.js Script on GitHub Pages or Amazon S3

Museum of Modern and Contemporary Art of Trento and Rovereto