CocoaHTTPServer
CocoaHTTPServer copied to clipboard
HTTPServer: -Dealloc causes memory corruption
Hi Robbie,
Summary:
The call to -stop:NO in -dealloc of HTTPServer.m can produce memory corruption because there is no check to see if the server has already been stopped.
Steps to Reproduce:
- Spin up an instance of HTTPServer as normal.
- Call
[myServerInstance stop:NO] - Call
[myServerInstance release] - Set
myServerInstance = nil
(steps 3 and 4 assume you're working in a manual reference counting environment.) You will need to repeat this process several times because the issue only manifests sometimes.
What's Going On:
We call -stop on our server instance just before releasing it, which triggers the -dealloc method of HTTPServer. That dealloc method calls -stop again, regardless of whether the server is running or not.
About 4 out of 5 times, there is no problem. But approximately 1 out of 5 times, ARC produces a warning that informs you, "memory address X is supposed to hold address 0x000012345 but instead holds address 0x0000987665. This is likely incorrect usage of objc_store_weak() or objc_load_weak(), break on objc_weak_error to debug."
Breaking on that symbol shows that `[HTTPServer dealloc] is the last method in the stack trace before the warning is produced.
How I Fixed It:
I removed my own call to [myServerInstance stop:NO] and just released and nilled the instance instead. -dealloc still calls -stop:NO, but that method is now only called once. After doing this, I am no longer able to produce the ARC warning, no matter how many times I stop and recreate the server instance.
Suggested Permanent Fix:
The -dealloc method should really only call -stop if the server is running.
Actually, a more robust solution would be to have -stop return immediately if the server isn't running. That way, if the method is called more than once from anywhere, this problem is avoided.
Nice bug report! Want to submit a PR?
Mother of god...I thought this project was dead and buried. I just filed the report to procrastinate on customer support emails.
Hahahahahaha. I mean, it is, but plenty of people are still using it.
Actually the problem is the underlying NSNetService, see http://www.openradar.me/28943305 for more information. The workaround is to nil out the delegate before releasing. In HTTPServer.m this is in 'unpublishBonjour'. The bonjourBlock is called synchronously so this should be good.
[[self class] performBonjourBlock:bonjourBlock];
[netService setDelegate:nil]; // added this line to workaround apples weaksauce
netService = nil;
Thanks!