There is a MFI device that is connected to iPhone 4S (6.0 GM) or to iPad (6.0 GM) via Bluetooth (2.1 + EDR). The project was built on Xcode 4.5 GM. When the app gets EAAccessoryDidDisconnectNotification it will send message [_eaSessionController closeSession];. All these worked nice in iOS 5.1.1 or earler. But on iOS6 with this message I got logs as follows:
-[NSCondition dealloc]: condition (<NSCondition: 0x2e5640> '(null)') deallocated while still in use
Break on _NSLockError() to debug.
Any ideas?
I came across the same issue. This warning is thrown when calling [NSStream close] upon receiving an EAAccessoryDidDisconnectNotification. There should be also some data exchange between the two devices just before the disconnection.
Breaking on _NSLockError will show that at the moment the object is deallocated, some of the threads spawned by the external accessory framework are waiting on conditions. One of those certainly waits on the condition that is being freed, which explains the warning thrown on the console.
I also noticed that the number of threads created by the external accessory framework keeps on growing each time the accessory disconnects then connects, and they seem to be just leaking.
It seems to me that somehow, the external accessory framework does not properly free the resources it allocates, which results in a lot of mess. One of the subsequent effects of this are crashes that happen inside one of those leaked threads during a call to OSAtomicCompareAndSwap64.
I managed to reproduce the issue using a basic sample in which the streams are scheduled on the main thread to avoid any thread management inside the application. I believe it's an accessory management bug on iOS 6 that Apple should be aware of. I'll report it and wait for what they have to say.
Meanwhile, I wonder if anyone of you guys has managed to make any progress on this.
Thanks,
There is no such trouble in iOS 6.1+. To fix this for iOS 6.0 and iOS 6.0.1 please use next solution:
Please note: this is only temp solution allow your users with iOS 6.0 and 6.0.1 continue use your app.
There is a simple hack to avoid application crashes: just create new category and override dealloc method (NSCondition) for iOS 6.0 and iOS 6.0.1:
#import "NSCondition+LeakDealloc.h"
#import <objc/runtime.h>
#implementation NSCondition (LeakDealloc)
- (void) safeDealloc
{
float sVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
if (sVersion < 6.0 || sVersion >= 6.1)
{
[self safeDealloc];
}
}
+ (void) load
{
method_exchangeImplementations(class_getInstanceMethod(self, #selector(dealloc)), class_getInstanceMethod(self, #selector(safeDealloc)));
}
#end
This solution make new leak, after 20 min tests and about 50 BG/FG swithces instruments shows 10 NSCondition leaks (960 Bytes), BUT no one crash!
The issue has been fixed in iOS 6.1.
There are no more leaking NSCondition or external accessory threads. Apple seem to having fixed the issue properly.
Related
I am trying to migrate to using Xcode 10 on Mojave, coming from using Xcode 8.3.3 on High Sierra. I have a sizeable app containing a fair bit of legacy (non-ARC) code. The app is currently live in the Mac App Store, built with 8.3.3 on High Sierra.
I encountered problems with Xcode 10 and Mojave which took me down a rabbit hole, so I decided to back up and limit the migration to one step at a time. I'm currently attempting (unsuccessfully) to build and run using Xcode 9.4.1 on High Sierra.
Using exactly the same code base (new repo checkout) my app builds and runs fine using Xcode 8.3.3. It builds fine using 9.4.1, but crashes on running.
The problem appears to be memory/reference-counting related. I always get a crash when the app tries to show a window, and the trace is not very helpful. Runtime debug output consistently indicates that I'm sending a message to a deallocated object. Here's a typical stack trace:
stack trace
Whenever the app tries to show a window, I get messages such as (the old favourite) "message sent to deallocated instance". I don't always recognise the receiver as being one of my properties, so it looks like this is just a symptom, not a cause. Here's a typical message:
*** -[NSCalibratedRGBColor release]: message sent to deallocated instance 0x60000605ce60
I've tried in vain to get anything back from Xcode's diagnostics, such as zombies and malloc scribble. Radio silence. Also the static analyser reports no problems.
All I can think is that manual reference counting is somehow being treated differently by Xcode 9. I've checked through all the build flags to see if Xcode 9 changed anything. No changes. I've checked the release notes and can find no mention of changes to reference counting.
I can push the problem around by commenting out the display of various panels and windows, but the crash always takes the same form.
Has anyone else come across similar issues and found a solution? Am I missing something with Xcode 9? Any help greatly appreciated.
Thanks #sdarlington and Willeke for very helpful answers. I finally found and fixed the problem. I did have to use the caveman approach and gradually remove stuff from a crashing window (as you rightly identified Stephen). Turns out it was a legacy retain/release issue that none of Xcode's diagnostics was catching.
I inherited an old graphics framework that doesn't use ARC. It declares ivars like this:
#interface ColourFiller : NSObject
{
NSColor* m_PrimaryColour;
NSColor* m_SecondaryColour;
}
...
#end
then sets them like this in its init method:
m_PrimaryColour = [NSColor colorWithCalibratedRed:1 green:1 blue:1 alpha:1];
m_SecondaryColour = [NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:1];
Note the lack of manual retain.
So I added one, and all is well:
m_PrimaryColour = [[NSColor colorWithCalibratedRed:1 green:1 blue:1 alpha:1] retain];
m_SecondaryColour = [[NSColor colorWithCalibratedRed:0 green:0 blue:0 alpha:1] retain];
I have no idea why Xcode wasn't flagging this, or indeed why all previous builds/xcode versions were running fine. This code has happily existed without symptoms for years. Some library changes must have been made by Apple in Xcode 9 that finally exposed it.
Thanks again for your help - I can now progress to Xcode 10 and Mojave.
Hei.
These two pictures below show what changed. Here's my code for it and the code didn't change.
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
if (section == 0) {
return #"If enabled, closing apps via the app switcher won't actually close the app itself.\n\nThis option is perfect to use with Fast Freeze.";
}
NSString *offDescription = #"OFF\nDisables the backgrounding capability completely. The app has to restart every time you close it.";
NSString *fastFreezeDescription = #"FAST FREEZE\nThis mode is similar to what 'Smart Close' by rpetrich did. Usually an app has up to 10 minutes to perform tasks in the background before it gets suspended in memory. Since this can be an unnecessary battery drain, Fast Freeze will suspend the app right after you close it.";
NSString *nativeDescription = #"NATIVE\nThis is Apple's built in way of backgrounding.";
NSString *unlimitedNativeDescription = #"UNLIMITED NATIVE\nThis background mode allows apps to execute background tasks for an unlimited period of time, so the app won't get suspended in memory after 10 minutes.";
NSString *foregroundDescription = #"FOREGROUND\nForeground tricks the system into thinking that the app wasn't closed and is still running in foreground. This is the perfect way to continue to listen to internet streams or videos while using another app.";
return [NSString stringWithFormat:#"\n%#\n\n%#\n\n%#\n\n%#\n\n%#", offDescription, fastFreezeDescription, nativeDescription, unlimitedNativeDescription, foregroundDescription];
}
Here are the screenshots:
This is the view before (iOS 8), notice that "\nOFF\nDisables ..." has the gap to the last UITableViewCell like it should be.
This is the view after (iOS 9), the gap is off. Too much space there.
So, does anyone know why this happens? If anyone has an fix or something, please tell me!
Thanks in advance!
This seems like an Apple's bug (iOS 9.0 - 9.1), the more lines footer has, the bigger misplacement gets.
You can even reproduce this in the storyboard using static table view.
I cound't find any workaround yet, the best advice I can give is to file a bug report to Apple.
Update
The bug in storyboard seems to be fixed in Xcode 7.2 beta 2. However this issue still persists when you run the app even on iOS 9.2 simulator.
Update 2
Narrowed down the reproduction of this bug. Basically something breaks after your app presents a table view section header. Check this repo for details.
I was just reading that this delegate has only been added in iOS 4.2
[CLLocationManagerDelegate locationManager:didChangeAuthorizationStatus:]
Turn out having that method crashed devices with older iOS version.
What would be the equivalent of that method in iOS 4.1 for example?
Thank you,
Tee
In earlier versions, you the locationManager:didFailWithError: delegate method will be called with error saying kCLErrorDenied
Having the locationManager:didChangeAuthorizationStatus: delegate method in your code did not cause your crash. Somewhere you must have sent an authorizationStatus message to the CLLocationManager instance which isn't recognized prior to 4.2.
I am new to iPhone programming. I am looking for an example or a demo on how to use startMonitoringSignificantLocationChanges method with the CoreLocation Manager.
I am confused by the documentation because, I am not sure if the same delegate method is called as in the case of invoking startUpdatingLocation. (i.e. the delegate locationManager: (CLLocationManager *)manager didUpdateToLocation: (CLLocation *)newLocation fromLocation: (CLLocation *)oldLocation is called)
Any help on this would be appreciated. Also, I am testing it on the simulator by subclassing of CLLocationManager. This subclass provides a simulation of location services when running on the iPhone Simulator. Is there a better way to test this.
I have done a bit of testing with the significant change API. I posted a sample project on GitHub that lets you play with regular and significant location updates.
This question might also shed some light on what happens when you get woken up for a significant change event.
Update
Another thing you should be aware of, there is a bug in CoreLocation in 4.1. Basically if your app is in the background, then it will crash when core location tries to wake you up. It is fixed in 4.2.
There is a great video session on these new iOS 4.0 CoreLocation and MapKit features from WWDC 2010 that should be freely available in iTunes U for all registered iPhone developers.
I have some code that needs to be run when the application terminates. I register my controller for the NSApplicationWillTerminateNotification as follows:
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: #selector(applicationWillTerminate:)
name: NSApplicationWillTerminateNotification
object: nil];
Now, if I start my app and quit it within the first 20 seconds or so, applicationWillTerminate gets called. If I quit the application later, it doesn't. What in my application could cause this behaviour? I have also tried to set up my controller as NSApplication's delegate with same results. Any ideas?
Thanks.
Oh, and this is XCode 3.2, Snow Leopard 10.6.1, using 10.5 SDK. Happens in both Debug and Release builds.
There are several reasons why this might be happening.
If you are running GC'd, does your observer get collected and finalized before the termination happens? (I should test this and file a bug if it does as that at least needs to be documented)
Is your app silently crashing or calling exit() directly?
In general, you cannot count on the termination notification being received as the user might go for a force quit for the heck of it.
Also, in Snow Leopard, there is a feature called sudden termination that allows your app to let the system know that it is safe to kill the app instead of going through the normal termination rigamarole. It is documented in the NSProcessInfo documentation.