Search Unity

Unity 4.2 - Seeing Crash on iOS Device when using SystemInfo.deviceUniqueIdentifier

Discussion in 'iOS and tvOS' started by SunstormDawson, Jul 23, 2013.

  1. SunstormDawson

    SunstormDawson

    Joined:
    Jul 23, 2013
    Posts:
    7
    I have recently converted a project from Unity 4.1.4f1 to Unity 4.2.0f4 and I am now seeing a crash when running the game on device. The project builds, deploys and runs without issue using Unity 4.1.4f4 and no code changes were necessary when converting the project to Unity 4.2.0f4. Below is an excerpt of the callstack pulled from Xcode.

    thread #1: tid = 0x2403, 0x3bb285b0 libobjc.A.dylib`objc_msgSend + 16, stop reason = EXC_BAD_ACCESS (code=1, address=0x37)
    frame #0: 0x3bb285b0 libobjc.A.dylib`objc_msgSend + 16
    frame #1: 0x00c0a418 game`UnityDeviceUniqueIdentifier + 80 at DeviceSettings.mm:37
    frame #2: 0x00da92f0 game`systeminfo::GetDeviceUniqueIdentifier() + 12 at iPhoneSettings.mm:234
    frame #3: 0x01060e64 game`SystemInfo_Get_Custom_PropDeviceUniqueIdentifier() + 44 at BaseClass.cpp:1827
    frame #4: 0x008e191c game`m_wrapper_managed_to_native_UnityEngine_SystemInfo_get_deviceUniqueIdentifier + 56
    frame #5: 0x00297490 game`m_ValPlayerPrefs_CheckAndInitializeKeys + 892

    The ValPlayerPrefs class is a PlayerPrefs wrapper that performs some encryption and validation; in the CheckAndInitializeKeys method the class stores the device unique identifier into a member variable for later use (one-liner below).

    deviceIDKey = SystemInfo.deviceUniqueIdentifier;

    I can post the full callstack if it would help. The cliff notes version of the callstack shows a level load followed by an Awake call to a script attached to an object in a scene, which in turn uses a singleton MonoBehaviour for the first time and that singleton calls the static ValPlayerPrefs.CheckAndInitializeKeys method in its Awake. I first thought this issue was something broken in the Unity 4.2 iOS player, but I tested an empty project that only logged out the unique identifier value and it worked without issue.

    Unfortunately, I am not that familiar with Xcode (using v4.6.3) debugging so I am having trouble determining the root cause of this issue in the project. My first debugging attempt was to try to use a Script Debugging enabled build of the project but I am unable to compile the project in Xcode with that option turned on due to a dsymutil failure (http://forum.unity3d.com/threads/146551-dsymutil-failed-with-exit-code-11). I enabled Objective-C Zombie Objects to attempt to get more information but the output was not much more help nor was the updated callstack.

    Console Output from Zombie info:
    2013-07-23 13:12:01.914 salon[736:907] *** -[CFString UTF8String]: message sent to deallocated instance 0x1f5a8220

    Updated callstack:
    * thread #1: tid = 0x2403, 0x33e4b468 CoreFoundation`___forwarding___ + 192, stop reason = EXC_BREAKPOINT (code=EXC_ARM_BREAKPOINT, subcode=0xdefe)
    frame #0: 0x33e4b468 CoreFoundation`___forwarding___ + 192
    frame #1: 0x33da2f68 CoreFoundation`__forwarding_prep_0___ + 24
    frame #2: 0x00b9c418 game`UnityDeviceUniqueIdentifier + 80 at DeviceSettings.mm:37
    frame #3: 0x00d3b2f0 game`systeminfo::GetDeviceUniqueIdentifier() + 12 at iPhoneSettings.mm:234
    frame #4: 0x00ff2e64 game`SystemInfo_Get_Custom_PropDeviceUniqueIdentifier() + 44 at BaseClass.cpp:1827
    frame #5: 0x0087391c game`m_wrapper_managed_to_native_UnityEngine_SystemInfo_get_deviceUniqueIdentifier + 56
    frame #6: 0x00229490 game`m_ValPlayerPrefs_CheckAndInitializeKeys + 892

    Is anyone else seeing this issue? Any ideas on what to try next?


    UPDATE:
    I located the externalized UnityDeviceUniqueIdentifier method in DeviceSettings.mm and was able to set a breakpoint there and track the use of the static _DeviceID NSString* in the UnityDeviceUniqueIdentifier and the QueryDeviceID method that it calls. Interestingly enough, the project did not crash at the same point but crashed during another call to SystemInfo.deviceUniqueIdentifier later.

    When debugging the project, the Unity start-up hardware reporting method causes the breakpoint to hit and the _DeviceID value is set without issue. The breakpoint hits again when the ValPlayerPrefs.CheckAndinitializeKeys method uses SystemInfo.deviceUniqueIdentifier and this time the game does not crash. The _DeviceID is recognized as already being set and it has a value. The breakpoint hits a third time when a DLL used by the project (this DLL was created internally) call SystemInfo.deviceUniqueIdentifier. This time the _DeviceID has a memory address but it has been deallocated and with Zombie Objects turned on I can see that the class is __NSZombie__.

    Is this something the project is doing wrong somehow or some issue on the Unity/Xcode side?
     
    Last edited: Jul 23, 2013
  2. kdoba

    kdoba

    Joined:
    Jul 23, 2013
    Posts:
    1
    I got the same error and fixed it by making sure _DeviceID string is retained properly. At DeviceSettings.mm:164
    Code (csharp):
    1. _DeviceID = [[NSString stringWithUTF8String:uid_str] retain];
     
  3. SunstormDawson

    SunstormDawson

    Joined:
    Jul 23, 2013
    Posts:
    7
    T'hanks, kdoba! I just did the same thing for _DeviceID as well as _VendorID and _ADID.

    I have submitted a bug to Unity for this; case 553416.
     
    Last edited: Jul 23, 2013
  4. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    yes, thats it. I'm sorry i fixed it for dev version (and anyway too late for 4.2). We'll push fix into 4.2.1 (or whatever it will be)
     
  5. SunstormDawson

    SunstormDawson

    Joined:
    Jul 23, 2013
    Posts:
    7
    Awesome! Thanks, Alexey.

    For now I have just had my team replace the DeviceSettings.mm file located on their machines at /Applications/Unity/Unity.app/Contents/PlaybackEngines/iPhonePlayer/iPhone-Trampoline/Classes/Unity/ with a version of the file I modified.
     
  6. nantas

    nantas

    Joined:
    Feb 11, 2010
    Posts:
    124
    Hey Alexey,

    My iOS game got a crash when using SystemInfo.deviceUniqueIdentifier for player profile encryption/decryption. The console log:

    CryptographicException: Bad PKCS7 padding. Invalid length 107.
    at Mono.Security.Cryptography.SymmetricTransform.ThrowBadPaddingException (PaddingMode padding, Int32 length, Int32 position) [0x00000] in <filename unknown>:0
    at Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in <filename unknown>:0
    at Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in <filename unknown>:0
    at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount) [0x00000] in <filename unknown>:0
    at GameProgress.DecryptBytes (System.String _key, System.Byte[] _toDecrypt) [0x0002e] in /Users/nantas/projects/money/Assets/Game/Scripts/System/GameProgress.cs:228

    Will the uniqueIdentifier for the same device stay the same between Unity 4.1.X build and Unity 4.2? If the uniqueIdentifier changed and we can't get the old one back our users will always got a crash when they update the game, and delete their profile and re-install is the only option.

    Thanks!
     
  7. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    it is a bit more complicated.
    for pre-ios7 we keep old behavior (hash of mac addr)
    on ios7 mac addr access is "removed" (it is forbidden to use it and you will get all zeroes) so we will get vendor id.
     
  8. nantas

    nantas

    Joined:
    Feb 11, 2010
    Posts:
    124
    I can see that, but will the uniqueIdentifier stay the same for pre-ios7 build? I re-installed Unity 4.1.5 last night and the crash is gone. I didn't run the game on device that has ios7 so I don't know why it act like the identifier is changed.

    Since in Unity 4.1.5, I can't find DeviceSettings.mm file, it's impossible for me to check if the algorithm is changed for pre-ios7 build.

    I will do more debugging today to print the uniqueIdentifier.
     
  9. serioustommy

    serioustommy

    Joined:
    Jun 12, 2012
    Posts:
    126

    Hi,

    A concern with this is that can we rely on the uniqueIdentifier for the same device being the same always even if the device is updated from iOS 6 to 7? It doesn't sound like it will? It might not be as useful for uniquely identifying a device (for the purpose of linking to a profile for example) if it can change just because the underlying OS changes.

    Thanks,
    Tommy
     
  10. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    well, the problem is that prev method of unique id no longer works. So yeah we kinda need to change that. On the bright side - you can save it to prefs and continue using it.
     
  11. luape

    luape

    Joined:
    Aug 1, 2013
    Posts:
    1
    We had the problem with unique id being different after upgrading to unity 4.2.
    After asking and digging into it more deeply, here is the answer if anyone needs:
    http://answers.unity3d.com/answers/506089/view.html

    EDIT: just realised my answer in the post is still being moderated.
     
  12. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
    what can i say, i can only cite mself from skype chat
    the answer on answers is actually correct one, we'll fix this S*** ASAP

    EDIT: you can change
    CC_MD5(macaddr_str, sizeof(macaddr_str), hash_buf);
    to
    CC_MD5(macaddr_str, sizeof(macaddr_str)-1, hash_buf);

    i will create sticky for now
     
    Last edited: Aug 2, 2013
  13. masterton

    masterton

    Joined:
    Dec 11, 2012
    Posts:
    41
    Hi Alexey - just want to confirm what will happen on iOS7.

    device id will return the vendor id instead of the hashed mac address, correct?

    My plan - on pre ios7 devices - is to save the vendor id along with the unique device id and allow login to occur with either the vendor id or unique identifier. That way, when iOS 7 does release and our users transitions to the new OS unique id will become vendor id and they will still be able to log into the correct account.

    Does that make sense?

    (I'm assuming vendor id is unique per device)
     
  14. Alexey

    Alexey

    Unity Technologies

    Joined:
    May 10, 2010
    Posts:
    1,624
  15. mateiasu

    mateiasu

    Joined:
    Mar 11, 2013
    Posts:
    25
    Do I understand this right. This fixes the issue with the still missing VendorID / UUID on iOS7 devices?

    Code (csharp):
    1. _VendorID = [(NSString*)[[[UIDevice currentDevice] performSelector:@selector(identifierForVendor)] UUIDString] retain];
    Is this piece of code correct as I 'fixed' it? (Sry, no objC coder at all)
     
    Last edited: Aug 14, 2013
  16. DannyB

    DannyB

    Joined:
    Jun 20, 2012
    Posts:
    214
    Hey,

    For the non-xcoders among us, can anyone please provide a list of changes that I need to place in DeviceSettings.mm to fix this? My game is crashing, and this may be the reason.

    I have updated line 164 to be
    Code (csharp):
    1. _DeviceID = [[NSString stringWithUTF8String:uid_str] retain];
    but I am unsure as to which other lines I need to update in regards to VendorID and ADID

    Thanks in advance.
     
    Last edited: Aug 31, 2013
  17. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    So, I understand that 4.2 broke some stuff and how to manually fix it in xcode....

    But can we please get a clear answer on ios 7+ SystemInfo.deviceUniqueIdentifier situation.

    So what I understand is that SystemInfo.deviceUniqueIdentifier is useless on ios7 and will return all zeros? What is all this talk about vendorId? Is vendorId unique for every device in all versions of ios? Also, how do we get the vendorId through the unity api?

    thanks

    -----------------------------------------


    Just found this post http://answers.unity3d.com/questions/519827/unique-identifier-for-both-ios-7-and-for-older-ios.html


    So we can use iPhone.vendorIdentifier - http://docs.unity3d.com/Documentation/ScriptReference/iPhone-vendorIdentifier.html on all versions of ios ?
     
    Last edited: Sep 12, 2013
  18. DannyB

    DannyB

    Joined:
    Jun 20, 2012
    Posts:
    214
    Well, as far as I can tell, here is the situation:

    1. Use Unity 4.2.1, it fixes the crash, no more need for manual fixing (confirmed)
    2. You may use uniqueDeviceIdentifier, only if using Unity 4.x (read: 4.2.1 and up). In Unity 3.5 it will be useless.
    3. If you wish. you may use the vendorId, but it is not necessary, as the uniqueDeviceIdentifier uses it in the background as a replacement for MAC addresses.
    4. You can access vendorId using iPhone.vendorIdentifier
     
  19. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    Awesome, thanks Danny B very clear :cool: !

    So the only thing I still don't totally understand is,... if I am using 4.2.1 which I am,.... when a user upgrades their device from ios6 to ios7 will the return from uniqueDeviceIdentifier be the same for that device or different??
     
  20. DannyB

    DannyB

    Joined:
    Jun 20, 2012
    Posts:
    214
    I believe it will be the same, as Unity tries to use vendorId if it is available (since iOS 6 if I recall). But I am a little fuzzy about that, maybe someone else can clarify with more certainty.

    But if you have already users of your game using a previous build, they will most likely have a new device ID when you release with 4.2.1

    I figured its an "accept the things you cannot change" type of scenario...
     
  21. blindgoat

    blindgoat

    Joined:
    Oct 24, 2012
    Posts:
    31
    I just ran some tests to confirm what was said before. Hopefully this will help someone else.

    iPad w/ iOS6
    Unity 4.1.3f3: deviceUniqueIdentifier= 12345000000 (example deviceId)
    Unity 4.2.0: deviceUniqueIdentifier= 5555000000 (has bug Alexey talks about in prev post)
    Unity 4.2.1: deviceUniqueIdentifier= 12345000000

    Same iPad w/iOS7
    Unity 4.1.3f3: deviceUniqueIdentifier= 0f607264fc6318a92b9e13c65db7cd3c (which is a hash of mac address 02:00:00:00:00:00)
    Unity 4.2.0: deviceUniqueIdentifier= 17C1AFF0-SODF-1232-SDFA-1S33BQASEBF90
    Unity 4.2.1: deviceUniqueIdentifier= 17C1AFF0-SODF-1232-SDFA-1S33BQASEBF90

    So 4.2.1 has the same deviceId as 4.1.x on iOS6 and the bug is in 4.2.0. On iOS7, the deviceId is totally different from what it was on iOS6.
     
    Last edited: Sep 13, 2013
  22. ccamfield

    ccamfield

    Joined:
    Jan 22, 2013
    Posts:
    2
    Hey all,

    We had our QA department report a crash in a certain situation in iOS7. I investigated it today, and it turned out to be this issue.

    Here's the thing. I'm still seeing the crash with Unity 4.2.1. There is no retain call executed when VendorID is retrieved. Unless by some chance I somehow screwed up updating Unity...

    Is anyone else still experiencing the problem in 4.2.1?


    P.S. Just to be clear, this is not an issue of _InitDeviceIDPreIOS7() is called. This is if that isn't executed, and QueryVendorID() is called instead. Line 127 in DeviceSettings.mm
     
    Last edited: Sep 13, 2013
  23. sims11tz

    sims11tz

    Joined:
    Nov 20, 2011
    Posts:
    15
    Yikes, we have not seen this yet.. but that sounds bad. Any clue on repro steps, like when are you calling for the vendor app?
     
  24. ccamfield

    ccamfield

    Joined:
    Jan 22, 2013
    Posts:
    2
    Possible false alarm! I think I screwed up. I didn't realize that we'd created an editor script to copy a custom version of the file to build xcode projects. So my build wasn't actually included the upgraded copy of the source code file.
     
  25. DannyB

    DannyB

    Joined:
    Jun 20, 2012
    Posts:
    214
    You had me worried there for a second... thanks for the correction.
     
  26. AnomalusUndrdog

    AnomalusUndrdog

    Joined:
    Jul 3, 2009
    Posts:
    1,553
    Hey y'all. Just to confirm, the bug does happen in Unity 3.5.

    I have a project using 3.5.7f6 and this is what it gives me:

    OS: iPhone OS 6.1.2, deviceUniqueIdentifier: b8f99f9be7a335e3a29809214304d7bd (works fine)
    OS: iPhone OS 7.0.2, deviceUniqueIdentifier: 0f607264fc6318a92b9e13c65db7cd3c (hash of MAC address 02:00:00:00:00:00)

    So if your project is still using Unity 3.5 and someone with iOS 7 plays your game, deviceUniqueIdentifier will always give the same value, regardless of the device. Better update to Unity 4.2.1 in that case.
     
    Last edited: Oct 3, 2013
  27. geniuscd

    geniuscd

    Joined:
    Aug 10, 2012
    Posts:
    23
    Hey All , I just tested what the "deviceUniqueIdentifier" returns and happy to share this.
    on iOS it will return a unique string every-time you removed the app from your iOS device.
    if you rebuilt the xcode project, without removing your app from the iphone, the same previous "deviceUniqueIdentifier" is returned. using 4.3.1