After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 655074 - [PATCH] Fix crash with undecorated windows on MacOS Lion
[PATCH] Fix crash with undecorated windows on MacOS Lion
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Backend: Quartz
2.24.x
Other Mac OS
: Normal major
: ---
Assigned To: gtk-quartz maintainers
gtk-bugs
: 655078 657663 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2011-07-21 19:41 UTC by Mikayla Hutchinson
Modified: 2012-01-06 19:00 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fixes the crash (1.55 KB, text/plain)
2011-07-21 19:41 UTC, Mikayla Hutchinson
  Details
Fixes the crash (2.59 KB, patch)
2011-07-21 20:54 UTC, Mikayla Hutchinson
rejected Details | Review
Combined patch (2.62 KB, patch)
2011-07-21 21:57 UTC, Mikayla Hutchinson
none Details | Review

Description Mikayla Hutchinson 2011-07-21 19:41:11 UTC
Created attachment 192416 [details]
Fixes the crash

Undecorated windows on MacOS Lion crash GTK, because it double-inits the NSWindow when setting the decoration.
Comment 1 Mikayla Hutchinson 2011-07-21 20:54:55 UTC
Created attachment 192421 [details] [review]
Fixes the crash
Comment 2 John Ralls 2011-07-21 21:00:09 UTC
Review of attachment 192421 [details] [review]:

setStyleMask is (officially) introduced in 10.6. 
The fix is actually simpler; just
[impl->toplevel release];
impl->toplevel = [[GdkQuartzNSWindow alloc] initContentWithRect...
(See 655078, which I'll make this a duplicate of.)
Comment 3 John Ralls 2011-07-21 21:01:18 UTC
Although 655078 is a little newer, it contains a more backward-compatible fix.

*** This bug has been marked as a duplicate of bug 655078 ***
Comment 4 Mikayla Hutchinson 2011-07-21 21:14:28 UTC
Not sure what you mean, checking the object responds to the selector is a perfectly backwards-compatible fix, and more correct.
Comment 5 Mikayla Hutchinson 2011-07-21 21:16:35 UTC
Also, my first patch implements the fix the way you other report describes.
Comment 6 Mikayla Hutchinson 2011-07-21 21:28:16 UTC
Note: both patches work fine on Lion, but I haven't tested on older OSes.
Comment 7 John Ralls 2011-07-21 21:33:16 UTC
(In reply to comment #4)
> Not sure what you mean, checking the object responds to the selector is a
> perfectly backwards-compatible fix, and more correct.

On the theory that if it doesn't respond to the selector the old way is OK? I guess, since Apple isn't going to go back and fix whatever they thought was broken.

(In reply to comment #5)
> Also, my first patch implements the fix the way you other report describes.

But you replaced that one with the new one, so I didn't look at it until now.

Are you worried about getting credit?

(In reply to comment #6)
> Note: both patches work fine on Lion, but I haven't tested on older OSes.

I've tested the first one on Lion and Snow Leopard. I'll test on Tiger and Leopard later, but there's no reason that it shouldn't work... and running init on an existing object is probably naughty anyway.
Comment 8 Mikayla Hutchinson 2011-07-21 21:44:44 UTC
 (In reply to comment #7)
> > Not sure what you mean, checking the object responds to the selector is a
> > perfectly backwards-compatible fix, and more correct.
> 
> On the theory that if it doesn't respond to the selector the old way is OK? I
> guess, since Apple isn't going to go back and fix whatever they thought was
> broken.

Nope, the selector check is better because using setStyleMask is more correct on the OSes that support it - I'm not convinced we aren't missing copying some properties from the old window to the new window - and it's less wasteful.

> (In reply to comment #5)
> > Also, my first patch implements the fix the way you other report describes.
> 
> But you replaced that one with the new one, so I didn't look at it until now.
> 
> Are you worried about getting credit?

I'm usually not too bothered by these things but I did just spend about 8 hours getting a full GTK+ source build on Mac set up just so that I could test my fix :)

> (In reply to comment #6)
> > Note: both patches work fine on Lion, but I haven't tested on older OSes.
> 
> I've tested the first one on Lion and Snow Leopard. I'll test on Tiger and
> Leopard later, but there's no reason that it shouldn't work... and running init
> on an existing object is probably naughty anyway.

Yeah, the double-init is evil but since I couldn't test older OSes I didn't want to change the behaviour there.

Probably the "best" solution is to combine both patches :)
Comment 9 John Ralls 2011-07-21 21:55:43 UTC
(In reply to comment #8)
>  (In reply to comment #7)
> > > Not sure what you mean, checking the object responds to the selector is a
> > > perfectly backwards-compatible fix, and more correct.
> > 
> > On the theory that if it doesn't respond to the selector the old way is OK? I
> > guess, since Apple isn't going to go back and fix whatever they thought was
> > broken.
> 
> Nope, the selector check is better because using setStyleMask is more correct
> on the OSes that support it - I'm not convinced we aren't missing copying some
> properties from the old window to the new window - and it's less wasteful.
> 
> > (In reply to comment #5)
> > > Also, my first patch implements the fix the way you other report describes.
> > 
> > But you replaced that one with the new one, so I didn't look at it until now.
> > 
> > Are you worried about getting credit?
> 
> I'm usually not too bothered by these things but I did just spend about 8 hours
> getting a full GTK+ source build on Mac set up just so that I could test my fix
> :)

You should have used http://gtk-osx.sourceforge.net . It would have taken you less than an hour, and with no pain. ;-)

> 
> > (In reply to comment #6)
> > > Note: both patches work fine on Lion, but I haven't tested on older OSes.
> > 
> > I've tested the first one on Lion and Snow Leopard. I'll test on Tiger and
> > Leopard later, but there's no reason that it shouldn't work... and running init
> > on an existing object is probably naughty anyway.
> 
> Yeah, the double-init is evil but since I couldn't test older OSes I didn't
> want to change the behaviour there.
> 
> Probably the "best" solution is to combine both patches :)

You're probably right. I'll get that worked up on 655078 for both Gtk-2.24 and master. They'll be checked in on gtk-2.24-quartz and quartz-integration soon (I'll have to knock off for a social engagement shortly, so perhaps not tonight); it will have to wait for Kris to decide what he wants to do for master.
Comment 10 Mikayla Hutchinson 2011-07-21 21:57:43 UTC
Created attachment 192427 [details] [review]
Combined patch

I've done it already :)
Comment 11 Mikayla Hutchinson 2011-07-21 22:02:03 UTC
(In reply to comment #9)
> You should have used http://gtk-osx.sourceforge.net . It would have taken you
> less than an hour, and with no pain. ;-)

Unfortunately I needed to build a GTK+ with Mono's patchset and gtk-sharp, so I ended up using Banshee's bockbuild.
Comment 12 John Ralls 2011-07-21 22:11:08 UTC
Thanks.
Comment 13 John Ralls 2011-07-21 22:11:48 UTC
*** Bug 655078 has been marked as a duplicate of this bug. ***
Comment 14 Kristian Rietveld 2011-07-22 05:57:09 UTC
(In reply to comment #10)
> Created an attachment (id=192427) [details] [review]
> Combined patch
> 
> I've done it already :)

I will put this on my review list.  I don't really understand why a double init does not work on Lion, maybe because of the new ref counting thing?

(Note: I will not have access to Lion in the near future unfortunately).
Comment 15 Mikayla Hutchinson 2011-07-22 08:16:53 UTC
(In reply to comment #14)
> I will put this on my review list.  I don't really understand why a double init
> does not work on Lion, maybe because of the new ref counting thing?

See the trace in bug 655078 - an internal method called by the initializer is asserting that an internal field is not null.
Comment 16 John Ralls 2011-07-22 12:30:30 UTC
Kris,

If you're not able to test, perhaps you should just check it for style and I can push it when you're happy with that. This is a blocker for a lot of programs, so we need to get it out ASAP.

I'll have it in both the quartz branches tonight, but there are plenty of folk who don't use those.
Comment 17 Paul Davis 2011-07-22 12:37:24 UTC
FWIW, we'll be checking this out with Ardour/Mixbus today as well. Mike & John - thanks for the work on this.
Comment 18 carbncl 2011-07-24 10:21:40 UTC
No idea if that helps, but just wanted to report that I applied that patch and confirm it is working.
Thanks @Michael Hutchinson for this! And great to see that this community is reactive. :)
Comment 19 Kristian Rietveld 2011-07-25 08:33:27 UTC
(In reply to comment #10)
> Created an attachment (id=192427) [details] [review]
> Combined patch
> 
> I've done it already :)

I've committed this to GTK+ 3 master (I will push shortly) with two changes:

 - Use GdkQuartzNSWindow.
 - Add guards so that the setStyleMask is not exposed to the compiler < 10.6 to avoid spewing warnings.


John: feel free to merge this into the gtk-2-24 branch, I don't have it checked out at the moment ...
Comment 20 John Ralls 2011-07-25 13:21:57 UTC
Done.
Comment 21 John Ralls 2011-07-27 09:56:27 UTC
(In reply to comment #19)

>  - Add guards so that the setStyleMask is not exposed to the compiler < 10.6 to
> avoid spewing warnings.
> 

Sorry I'm a bit late on this, I didn't really think it through until I had to reconcile it with quartz-integration.

The guards miss the whole point of the runtime check. Micheal's intent was that regardless of what SDK it's built on, and regardless of what mac_osx_version_min is, setStyleMask will be used if it's available rather than having to create a new object. 

Yes, it produces a compile-time warning because the compiler isn't smart enough to recognize the run-time check. If you really insist on squashing that, get rid of the (very expensive) ifRespondsToSelector call.
Comment 22 Kristian Rietveld 2011-07-27 10:12:37 UTC
(In reply to comment #21)
> (In reply to comment #19)
> 
> >  - Add guards so that the setStyleMask is not exposed to the compiler < 10.6 to
> > avoid spewing warnings.
> > 
> 
> Sorry I'm a bit late on this, I didn't really think it through until I had to
> reconcile it with quartz-integration.
> 
> The guards miss the whole point of the runtime check. Micheal's intent was that
> regardless of what SDK it's built on, and regardless of what
> mac_osx_version_min is, setStyleMask will be used if it's available rather than
> having to create a new object. 

Hrm, my intent was to not have the compiler warning on older systems and if you compile on a newer system it would produce a backwards compatible binary.

But thinking of it more, if you compile on a newer system, you would likely compile it under the 10.4 SDK, right?  Does that set version_min to 10.4 so that the code breaks again?  (I guess so actually ...)
Comment 23 John Ralls 2011-07-27 11:07:58 UTC
No, it's worse than that.
There are two environment variables at play here, MAC_OS_X_VERION_MIN_ALLOWED and MAC_OS_X_VERSION_MAX_AVAILABLE. Either can be explicitly set in the environment, but usually neither is explicitly. In that case, MAX_AVAILABLE is set to the SDK used for the build and MIN_ALLOWED is set to the higher of $MACOSX_DEPLOYMENT_TARGET or the -mmacosx_version_min compiler flag. If neither is set, it is also set to the SDK version.

http://developer.apple.com/library/mac/#technotes/tn2064/_index.html has the gory details.

What I've been doing for some time is building against the lowest-targeted SDK, which because WebKitGTK won't build against 10.4 has been 10.5. But Lion's XCode 4.1 doesn't support SDKs before 10.6, so I (and every other Mac Gtk maintainer who wants to move to Lion) will have to start doing what Apple says they want us to do in that technote: Use SDK 10.6 or 10.7 and set -mmacosx_version_min (or $MACOSX_DEPLOYMENT_TARGET) to 10.4 or 10.5. 

The thing about Objective-C is that it can link method calls at runtime (that's the weak linking they talk about in the tech note), so even if a method isn't in the header when you compile you can still use it if you check beforehand with respondsToSelector, which is what Michael does here, so even when you compile his version of the patch against SDK10.5, it will produce the compiler warning because the method isn't in the 10.5 header -- but it's weak linked anyway, so when it's run on 10.6 or 10.7, it will find the method in the framework in /System/Library/Frameworks and execute it.
Comment 24 Kristian Rietveld 2011-07-28 15:38:55 UTC
(In reply to comment #23)
> No, it's worse than that.
> There are two environment variables at play here, MAC_OS_X_VERION_MIN_ALLOWED
> and MAC_OS_X_VERSION_MAX_AVAILABLE. Either can be explicitly set in the
> environment, but usually neither is explicitly. In that case, MAX_AVAILABLE is
> set to the SDK used for the build and MIN_ALLOWED is set to the higher of
> $MACOSX_DEPLOYMENT_TARGET or the -mmacosx_version_min compiler flag. If neither
> is set, it is also set to the SDK version.
> 
> http://developer.apple.com/library/mac/#technotes/tn2064/_index.html has the
> gory details.
> 
> What I've been doing for some time is building against the lowest-targeted SDK,
> which because WebKitGTK won't build against 10.4 has been 10.5. But Lion's
> XCode 4.1 doesn't support SDKs before 10.6, so I (and every other Mac Gtk
> maintainer who wants to move to Lion) will have to start doing what Apple says
> they want us to do in that technote: Use SDK 10.6 or 10.7 and set
> -mmacosx_version_min (or $MACOSX_DEPLOYMENT_TARGET) to 10.4 or 10.5. 

I see.


> The thing about Objective-C is that it can link method calls at runtime (that's
> the weak linking they talk about in the tech note), so even if a method isn't
> in the header when you compile you can still use it if you check beforehand
> with respondsToSelector, which is what Michael does here, so even when you
> compile his version of the patch against SDK10.5, it will produce the compiler
> warning because the method isn't in the 10.5 header -- but it's weak linked
> anyway, so when it's run on 10.6 or 10.7, it will find the method in the
> framework in /System/Library/Frameworks and execute it.

Yea, I understood that.   I only really tried to get rid of the compiler warning, because in GTK+ we try hard to have the code compile without warnings.  (I know there's currently some other warnings related to event masks in gdk/quartz/, I have a patch on my other machine that fixes this).  I forgot to think of the case when you compile for an older SDK on a newer SDK machine.

I will remove the #ifdef I added and have to learn to live with the compile warning on Tiger for now ;)  I tried to look for a way to suppress the compile warning on older platforms (perhaps a compiler flag), but it doesn't seem easily possible and it is probably not worth the effort.
Comment 25 John Ralls 2011-08-01 21:21:12 UTC
There's a rather involved way to get rid of the compile warning:
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -2589,7 +2589,14 @@ gdk_quartz_window_set_decorations (GdkWindow       *window,
        */
       if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
         {
-          [impl->toplevel setStyleMask:new_mask];
+	  NSMethodSignature *sig =
+	    [impl->toplevel methodSignatureForSelector:@selector(setStyleMask)];
+	  NSInvocation *method =
+	    [NSInvocation invocationWithMethodSignature:sig];
+	  gpointer mask_ptr = &new_mask;
+	  [method setSelector:@selector(setStyleMask:)];
+	  [method setArgument:mask_ptr atIndex:2];
+	  [method invokeWithTarget:impl->toplevel];
         }
       else
         {

(It would be easier if setStyleMask took a pointer to something instead of an int: [impl->toplevel performSelector:@selector(setStyleMask) withObject:foo] instead of all the MethodSignature and Invocation stuff, but it doesn't.)

Anyway, if you think it worthwhile, I can commit it.
Comment 26 Kristian Rietveld 2011-08-13 19:18:29 UTC
(In reply to comment #25) 
> (It would be easier if setStyleMask took a pointer to something instead of an
> int: [impl->toplevel performSelector:@selector(setStyleMask) withObject:foo]
> instead of all the MethodSignature and Invocation stuff, but it doesn't.)
> 
> Anyway, if you think it worthwhile, I can commit it.

I thought about an invocation like this, but it doesn't really help readability as you would likely agree with me ;)  

I propose we leave things as they are currently, if people really start complaining about the compile warnings, we can always introduce something like this.
Comment 27 John Ralls 2011-08-13 20:15:52 UTC
Yup, it's ugly, and it would have to be heavily commented to explain what's going on and why.

I doubt that anyone will complain. It's not like it's the only warning.
Comment 28 Alex Corrado 2011-10-03 21:59:16 UTC
Hey guys, I know you've closed this bug, but I just want to mention that you can get rid of that warning by doing something similar to what I proposed in bug #516725. Basically, define a protocol that has the signature of the setStyleMask method and then cast impl->toplevel to an id that implements that. Something like:

@protocol CanSetStyleMask
- (void)setStyleMask:(int)mask;
@end

if ([impl->toplevel respondsToSelector:@selector(setStyleMask:)])
{
    [(id<CanSetStyleMask>)impl->toplevel setStyleMask:new_mask];

...
Comment 29 John Ralls 2011-10-09 17:18:57 UTC
So it does. I'd forgotten about that trick. Committed to gtk-2-24, gtk-3-2, and master. Thanks!
Comment 30 John Ralls 2012-01-06 19:00:12 UTC
*** Bug 657663 has been marked as a duplicate of this bug. ***