gnustep-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Intentionally crashed my Web development kit, got this gem.


From: 陈北宗
Subject: Re: Intentionally crashed my Web development kit, got this gem.
Date: Sun, 6 Dec 2015 05:01:02 +0800

Ivan

What I am trying to highlight here is that Apple probably implemented their TFB using @defs() (ever heard of it?) - something that cannot be used cross-binary reliably but guarantees compatibility between pointers of TFB-enabled classes defined within a single binary, as @defs() guarantees identical layout of an Objective-C class and a C struct. Our current TFB mechanism depend on implementation detail of Base and does not scale well into Opal (CGPath path = …; CFRelease(path); crashes).

So here is my proposal, outline of how Apple implemented their TFB which not only works for CF but also CG, CA and more:

1) Memory management is always done using Objective-C runtime. CFRetain(), [NSObject retain], objc_retain() set, CFRelease(), [NSObject release], objc_release() set as well as a few sets regarding autorelease pools are synonymous and can be made aliases. (There are so many CFRetain((__bridge CFTypeRef)someObjectiveCObjectNotEvenTFBCompatible); in CGIJSONRPC code and it is surprisingly reliable despite being rich in black magic I never bothered to document. For once I overrode objc_retain() with CFRetain() and that caused a stack overflow, revealing the fact that CFRetain calls objc_retain()) More to come on this later.
2) All CF types have a companion Objective-C class, either lumped to _NSCFType with some additional memory allocated, or as their independent umbrella classes’ subclasses like _NSArrayI or _NSCFString. I would suggest never lumping things together in our code and never have a _NSCFType in the first place (@compatibility_alias _NSCFTypeRef NSObject;), and for each and every CF type create an Objective-C counterpart type, essentially make all our CF-like types TFB to some Objective-C type, public or not.
3) All polymorphic functions, namely CFHash(), CFDescription(), CFEqual(), CFGetTypeID() and more are handled in Objective-C using their respective NSObject properties NSObject.hash, NSObject.description and functions [NSObject isEqual:], [NSObject typeID] and more.
4) The “basic methods” documented for basic data types have some significance: the basic data type umbrella classes as well as their CF counterparts implement methods not on their basic methods list using those basic methods instead of any implementation detail, and the basic methods themselves call the counterparts when an instance of its counterpart is encountered - [NSArray objectAtIndex:] calls CFArrayGetValueAtIndex() if the underlying type is a real CFArrayRef (discovered by intentionally crashing [NSArray enumerateObjectsUsingBlock:].)
5) All those CF*Retain(), CF*Release() always end up calling CFRetain() and CFRelease() - we can just alias them (preferably using symbol re-export) to reduce code size. CF*GetTypeID() are used as implementations for CFGetTypeID() but we can alias them too as we implemented CFGetTypeID by going back to their Objective-C counterparts.

The same applies to almost all types that have a *Ref type, especially CG, CA and AU, except NSZone and CFAllocatorRef. Those two, though, can also be TFB’d, and my example above depend on NSZone and CFAllocator being TFB pair.

So since you mentioned CA, here is an example of CGPathRef using the trick:

@interface _GSCGPath : NSObject <NSCopying> // Marking copyable CF types’ counterparts with NSCopying may be a good habit. The copyWithZone: method can be bridged over to CF*CreateCopy().
{
  // ivars
}
// …
@end

struct _CGPath
{
  @defs(_GSCGPath);
}

CGMutablePathRef CGPathCreateMutable(CFAllocatorRef allocator)
{
  _GSCGPath *path = [[_GSCGPath allocWithZone:allocator] initMutable]; // This is the trick
  return CFBridgingRetain(path); // ARC habits die hard, but still works
}

CGPathRef CGPathRetain(CGPathRef) __attribute__((alias(“CFRetain”)));
void CGPathRelease(CGPathRef) __attribute__((alias(“CFRelease”)));

In fact, given then location of functions, we can even do this if ARC in libobjc2 is mandated:

CFTypeRef CFRetain(CFTypeRef) __attribute__((alias(“objc_retain”)));
void CFRelease(CFTypeRef) __attribute__((alias(“objc_release”)));

About how Apple implemented their CA it is unimportant indeed - their entire graphics stack is different. But as it is heavily CF-like code this TFB mechanism will affect it. Also since X11 is on its slow way out I would suggest write Opal on top of EGL as it is a graceful way of handling X11, Wayland and Mir at the same time without using a new “back” for the graphics stacks. The reason of suggesting direct EGL manipulation comes from the fact we may need SceneKit and SpriteKit down the road and those game-oriented frameworks will need direct OpenGL manipulation, and by doing this we can introduce our SpriteKit and SceneKit by inserting them between Opal and EGL, using Opal itself as a test suite.

By the way, both Wayland and Mir drew inspiration from WindowServer as well as EGL from QuartzExtreme, at least to me (it wouldn’t be the first Linux community drew inspiration from Apple - I am looking at you, systemd, a launchd workalike.) If we end up writing our own Wayland-based compositor with this EGL-based graphics stack we can create something architecturally similar to OS X.

Max

On Dec 6, 2015, at 03:49, Ivan Vučica <address@hidden> wrote:

北宗,

Your enthusiasm is commendable, but it is not important for GNUstep where Cocoa's NSException symbol lives. As long as it is available when you link with Foundation, the exact executable image in which it is distributed is Cocoa's implementation detail.

This was already discussed in previous instances where you outlined implementation details of Cocoa which are not required for correct functionality of GS.

Similarly, Cocoa's Core Animation happens to be largely implemented in C++. Does it matter that GNUstep's is implemented in Objective-C, or is it gaps in functionality that are actually important?

On Sat, Dec 5, 2015 at 6:08 PM 陈北宗 <address@hidden> wrote:
Testing for robustness of my Web development kit, and the default exception handler caught this gem:

System Crash: NSException

Name: NSInternalInconsistencyException

Reason: [CGIAppDelegate application:handleContext:] (/Users/……/Developer/CGIKit/CGIHello/CGIAppDelegate.m:44): This is just a test, don't panic.

User information:

KeyValue
(none)

Call stack:

0   CoreFoundation                      0x00007fff8aed1ae2 __exceptionPreprocess + 178
1   libobjc.A.dylib                     0x00007fff99b8c73c objc_exception_throw + 48
2   CoreFoundation                      0x00007fff8aed198d +[NSException raise:format:] + 205
3   CGIHello                            0x0000000100002650 -[CGIAppDelegate application:handleContext:] + 2640
4   CGIKit                              0x000000010002706d -[CGIApplication(CGIDelegatedMethods) handleContext:] + 93
5   CGIKit                              0x000000010002000d -[CGIContext run] + 109
6   Foundation                          0x00007fff8a411d4b __NSThreadPerformPerform + 279
7   CoreFoundation                      0x00007fff8ade15c1 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
8   CoreFoundation                      0x00007fff8add341c __CFRunLoopDoSources0 + 556
9   CoreFoundation                      0x00007fff8add293f __CFRunLoopRun + 927
10  CoreFoundation                      0x00007fff8add2338 CFRunLoopRunSpecific + 296
11  Foundation                          0x00007fff8a40fe61 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 270
12  CGIKit                              0x000000010002679f -[CGIApplication run] + 463
13  CGIKit                              0x0000000100027238 CGIApplicationMain + 248
14  CGIHello                            0x0000000100001b6b main + 91
15  libdyld.dylib                       0x00007fff98dac5ad start + 1


So NSException is defined in CoreFoundation… Maybe I should generate more crashes to probe OS X a bit...
_______________________________________________
Gnustep-dev mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/gnustep-dev


reply via email to

[Prev in Thread] Current Thread [Next in Thread]