Closed Bug 772179 Opened 12 years ago Closed 11 years ago

'Gestalt' is deprecated in Mac OS X 10.8

Categories

(Core :: Widget: Cocoa, defect)

x86
macOS
defect
Not set
normal

Tracking

()

RESOLVED FIXED
mozilla22

People

(Reporter: Nomis101, Assigned: areinald.bug)

References

(Blocks 1 open bug)

Details

Attachments

(1 file, 4 obsolete files)

Gestalt is deprecated since Mac OS X 10.8. If I build on 10.8 with the 10.8 SDK I get over 50 warnings in the kind of:

mozilla/xpcom/base/nsStackWalk.cpp:111:19: warning: 
      'Gestalt' is deprecated: first deprecated in Mac OS X 10.8
      [-Wdeprecated-declarations]
    OSErr err = ::Gestalt(gestaltSystemVersion, (SInt32*)&gOSXVersion);
                  ^
mozilla/xpcom/base/nsStackWalk.cpp:111:11: warning: 
      unused variable 'err' [-Wunused-variable]
    OSErr err = ::Gestalt(gestaltSystemVersion, (SInt32*)&gOSXVersion);
          ^
mozilla/xpcom/base/nsStackWalk.cpp:117:13: warning: 
      unused function 'OnLionOrLater' [-Wunused-function]
static bool OnLionOrLater()
            ^



mozilla/netwerk/protocol/http/nsHttpHandler.cpp:778:12: warning: 
      'Gestalt' is deprecated: first deprecated in Mac OS X 10.8
      [-Wdeprecated-declarations]
    if ((::Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) &&
           ^
/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Gestalt.h:123:1: note: 
      'Gestalt' declared here
Gestalt(
^
mozilla/netwerk/protocol/http/nsHttpHandler.cpp:779:12: warning: 
      'Gestalt' is deprecated: first deprecated in Mac OS X 10.8
      [-Wdeprecated-declarations]
        (::Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) {
           ^
/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Gestalt.h:123:1: note: 
      'Gestalt' declared here
Gestalt(
^



mozilla/widget/cocoa/nsCocoaFeatures.mm:60:23: warning: 
      'Gestalt' is deprecated: first deprecated in Mac OS X 10.8
      [-Wdeprecated-declarations]
        OSErr err = ::Gestalt(gestaltSystemVersion, ...
                      ^
1 warning generated.



mozilla/toolkit/xre/nsNativeAppSupportCocoa.mm:117:17: warning: 
      'Gestalt' is deprecated: first deprecated in Mac OS X 10.8
      [-Wdeprecated-declarations]
  OSErr err = ::Gestalt (gestaltSystemVersion, &response);
                ^
3 warnings generated.
Assignee: nobody → areinald
Attachment #722210 - Flags: review?
Comment on attachment 722210 [details] [diff] [review]
Changed method of discovering mac os version

Steven, the author of the bit of code I changed is not a bugzilla user, so I turned to you.
Attachment #722210 - Flags: review? → review?(smichaud)
Comment on attachment 722210 [details] [diff] [review]
Changed method of discovering mac os version

I think the basic approach is fine, but we shouldn't assume major versions greater than 8 are still 8.  In other words, I think you should drop the following from your patch:

+    else if (minor > 8) {
+      NS_ERROR("OS X version too new, assuming 10.8");
+      mOSXVersion = MAC_OS_X_VERSION_10_8_HEX;
+    }

Dealing with this bug is complicated by the fact that, as best I can tell, Apple doesn't have any official replacement for Gestalt!  That is a good reason to simply postpone finding any replacement for Gestalt ourselves.

But /System/Library/CoreServices/SystemVersion.plist has been around for a long time, and parts of Apple's UI have (unofficially at least) for a long time used it to find out what OS version is running.  (On OS X Server there's also a /System/Library/CoreServices/ServerVersion.plist, which uses the same syntax, and whose presence tells the same parts of Apple's UI that "server" is running instead of "client".)  So though your patch (apparently) relies on undocumented information, I think it's probably quite safe.

When I looked at this bug a few months ago, I was able to find an Apple doc that said we should use sysctl() as a replacement for Gestalt.  But I can no longer find it, and in any case there are problems using sysctl():

This isn't because of any problems with sysctl() itself.  Instead the version information read by sysctl() (and put in place by Apple) doesn't always match the "official" version number.  For example if you use "uname -a" on OS X 10.7.5 (which reads the same information read by systcl()), you get version 11.4.2, not 11.5.[n] as you should.

By the way, how did you decide to use /System/Library/CoreServices/SystemVersion.plist?  And why didn't you tell us? :-)
Attachment #722210 - Flags: review?(smichaud) → review+
Comment on attachment 722210 [details] [diff] [review]
Changed method of discovering mac os version

Another thing:

+  if ( versions.count >= 1 ) {
+    major = [versions[0] integerValue];
+    if ( versions.count >= 2 ) {
+      minor = [versions[1] integerValue];
+      if ( versions.count >= 3 ) {
+        bugfix = [versions[2] integerValue];
+      }
+    }
+  }

I'm not sure the syntax you use here (versions.count and versions[n]) is supported on older versions of OS X.  You should do a tryserver build to check.

Or now that I think of it, last I knew you still didn't have permission to use the tryservers, so I'll do a build myself.
Comment on attachment 722210 [details] [diff] [review]
Changed method of discovering mac os version

And yet another thing:

+    else if (minor < 5) {
+      NS_ERROR("OS X version too old, assuming 10.5");

The oldest version of OS X we currently support is 10.6.  So if in doubt you should assume 10.6, not 10.5.
Comment on attachment 722210 [details] [diff] [review]
Changed method of discovering mac os version

Note that if/when Apple does deign to document an official replacement for Gestalt (and if it's not what what this patch does), we'll have to revisit this bug, and possibly change what we've done here.
Comment on attachment 722210 [details] [diff] [review]
Changed method of discovering mac os version

Also please make the styling (e.g. the size of the indents) match what's already in this file.
(Following up comment #4)

This syntax doesn't work even on OS X 10.8.2 with a recent version of XCode -- it failed when I tried to build locally.  You'll need to change it.
(Following up comment #8)

I find the following syntax works for me:

    NSUInteger count = [versions count];
    if (count >= 1) {
        major = [(NSString *)[versions objectAtIndex:0] integerValue];
        if (count >= 2) {
            minor = [(NSString *)[versions objectAtIndex:1] integerValue];
            if (count >= 3) {
                bugfix = [(NSString *)[versions objectAtIndex:2] integerValue];
            }
        }
    }
Changed the patch to take into account Steven's comments. Actually I reformatted the whole source file (which is very short) to match our current "coding style" (no tabs, 2 space indent).
Attachment #722210 - Attachment is obsolete: true
Attachment #722395 - Flags: review?(smichaud)
(In reply to André Reinald from comment #10)
> Changed the patch to take into account Steven's comments. Actually I
> reformatted the whole source file (which is very short) to match our current
> "coding style" (no tabs, 2 space indent).

Ah, I'd like to know more about this. Is this encouraged, or should we avoid doing this because it messes up hg blame?
> I think the basic approach is fine, but we shouldn't assume major
> versions greater than 8 are still 8.  In other words, I think you
> should drop the following from your patch:
>
> +    else if (minor > 8) {
> +      NS_ERROR("OS X version too new, assuming 10.8");
> +      mOSXVersion = MAC_OS_X_VERSION_10_8_HEX;
> +    }

On reflection you should also change this

+    else {
+      int translated[] = {
+        MAC_OS_X_VERSION_10_5_HEX,
+        MAC_OS_X_VERSION_10_6_HEX,
+        MAC_OS_X_VERSION_10_7_HEX,
+        MAC_OS_X_VERSION_10_8_HEX
+      };
+      mOSXVersion = translated[minor - 5];
+    }

to this

    else {
            mOSXVersion = 0x1000 + (minor << 4);
    }

This may all need to change when OS X hits version 10.  But knowing
Apple, we'll just have to wait to see what they do when the time
comes.
>> Changed the patch to take into account Steven's comments. Actually
>> I reformatted the whole source file (which is very short) to match
>> our current "coding style" (no tabs, 2 space indent).
>
> Ah, I'd like to know more about this. Is this encouraged, or should
> we avoid doing this because it messes up hg blame?

I *really* *don't* like it :-)

For the reason you gave -- that it messes up hg blame.

Sometimes a file has inconsistent style.  In those cases I may change
the style of part of it -- but only those parts my patch would have
touched anyway.
André, you need to change you patch's syntax to match comment #9.  Also please make the change I recommend in comment #12.

As for reformatting the whole file, I could go either way -- the file's very short.

But in general I really hate style-only changes in a substantive patch.
Previous patch was already avoiding dotted property syntax. Wasn't it ? I changed to int to NSUInteger also. And adjusted formatting to the rest of the source file.
Attachment #722395 - Attachment is obsolete: true
Attachment #722395 - Flags: review?(smichaud)
Attachment #722404 - Flags: review?(smichaud)
> versions[0]

This kind of syntax is also new, and I'm not sure it'd work building on (say) OS X 10.6, with older versions of XCode.
Ok, let me change that... then I have to leave, it's 9 pm here :-)
Replaced versions[index] with [versions objectAtIndex:index]
Sorry I didn't notice that difference in your snippet.
Attachment #722404 - Attachment is obsolete: true
Attachment #722404 - Flags: review?(smichaud)
Attachment #722416 - Flags: review?(smichaud)
(In reply to Steven Michaud from comment #16)
> > versions[0]
> 
> This kind of syntax is also new, and I'm not sure it'd work building on
> (say) OS X 10.6, with older versions of XCode.

http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/ObjCAvailabilityIndex/index.html

Looks like it requires Xcode4.4 and deploys back to 10.6
> Looks like it requires Xcode4.4 and deploys back to 10.6

XCode 4.4 is still very recent.

Perhaps I'm being too conservative.  But our lives are complicated enough already without increasing the complication for no compelling reason.

Yes, I suppose the dot-property and subscript notations are simpler and friendlier.  But they're a drop in the ocean, and the older syntax they replace is only very moderately less friendly.
Comment on attachment 722416 [details] [diff] [review]
Changed method of discovering mac os version

Just one last, little change is needed.  And there's no problem letting it wait for tomorrow.

>+        major = [[versions objectAtIndex:0] integerValue];

This should really be

+        major = [(NSString*)[versions objectAtIndex:0] integerValue];

An NSArray holds NSObject objects, but integerValue is an NSString method.

It's possible your compiler doesn't complain about this.  But it really *should* :-)
The compiler may emit a warning because we call a method on an untyped ObjC object, I didn't check compiler output for warnings, as there are already so many!

I corrected with a twist: as the expression became quite long and was repeated 3 times, I factorized into a single function. So if you want other changes I'll only have to change once :-)
Attachment #722416 - Attachment is obsolete: true
Attachment #722416 - Flags: review?(smichaud)
Attachment #722709 - Flags: review?(smichaud)
Comment on attachment 722709 [details] [diff] [review]
Changed method of discovering mac os version

Looks fine to me.

Thanks for your patch.  Thanks particularly for the idea of using SystemVersion.plist.  You still haven't told us how you decided to do this :-)
Attachment #722709 - Flags: review?(smichaud) → review+
By the way, I don't know if you yet have permissions to land patches on the tree.  If so I'll just land this myself (on mozilla-inbound).
I thought I wrote where I found the trick, though they disagree with it:
http://cocoadev.com/wiki/DeterminingOSVersion

And I don't have permission to land patches in mozilla-inbound, which is fine to me, so I have less responsibility :-)
Comment on attachment 722709 [details] [diff] [review]
Changed method of discovering mac os version

Landed on mozilla-inbound:
https://hg.mozilla.org/integration/mozilla-inbound/rev/495fb4bf05f8

> http://cocoadev.com/wiki/DeterminingOSVersion

Thanks for the info.

Interesting that this doc doesn't mention sysctl at all.  Also interesting that "Apple recommended at the 2012 WWDC" to use SystemVersion.plist.  So that may actually become the official replacement for Gestalt.

But I suspect there will be a few more twists and turns before Apple finally gets its act together on this issue :-(
https://hg.mozilla.org/mozilla-central/rev/495fb4bf05f8
Status: NEW → RESOLVED
Closed: 11 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla22
(Following up comment #3)

> When I looked at this bug a few months ago, I was able to find an
> Apple doc that said we should use sysctl() as a replacement for
> Gestalt.  But I can no longer find it ...

I started to wonder if Apple might have suppressed this doc.  But no,
I've now looked more carefully and found it again:

http://developer.apple.com/library/mac/#releasenotes/General/CarbonCoreDeprecations/index.html#//apple_ref/doc/uid/TP40012224-CH1-SW16
(In reply to Steven Michaud from comment #28)
> (Following up comment #3)
> I started to wonder if Apple might have suppressed this doc.  But no,
> I've now looked more carefully and found it again:
> 
> http://developer.apple.com/library/mac/#releasenotes/General/
> CarbonCoreDeprecations/index.html#//apple_ref/doc/uid/TP40012224-CH1-SW16

And I guess you'd rather call sysctl than read the info from the plist :-)
I can submit another patch, that won't be long to write.
No, Andre, you don't understand why I commented.

I strongly prefer your patch to using sysctl, for the reasons I gave in comment #3.

I just wanted to show a complete history to-the-present of Apple's bumbling on this issue.
Do we need this kind of fix for all Components in which we are using 'Gestalt' (xpcom, netwerk, ipc, media, gfx, dom, toolkit)?
What we really need is for someone make all our OS X version queries use nsCocoaFeatures::OSXVersion().

This isn't urgent.  But then neither is it urgent to stop using Gestalt.

Apple has botched the transition away from Gestalt very badly.  They can't possibly get rid of it until well after they have an official replacement -- which they still don't have.  (By an official replacement I mean one that's documented in some kind of footnote to the original Gestalt documentation.)

Nonetheless, it'd still be nice to see someone clean up our OS X version checking code.  Interested? :-)
Looking into how to retrieve the version number, I fell on this bug... Accessing /System/Library/CoreServices/SystemVersion.plist isn't possible if the application is sandboxed.. And sooner or later, we'll have to be
Unfortunately my Mac Developer Program expired, so I can't link to the Apple docs, but [[NSProcessInfo processInfo] operatingSystemVersion] should return a NSOperatingSystemVersion struct which contains three NSIntegers. majorVersion, minorVersion, and patchVersion.

This is supposedly the "official" replacement we've been waiting for, but it's only available on 10.10.
> Accessing /System/Library/CoreServices/SystemVersion.plist isn't possible if the application is sandboxed.

Until all supported versions of OS X support Apple's official method to get the OS version, we'll have to add a rule to the sandbox ruleset to allow this access.  And if we sandbox NPAPI plugins, we'll probably also need to add exceptions to allow all kinds of other, unofficial ways to determine the OS version.
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: