As to your first paragraph - I understood the concept completely after my
debugging session and a few looks at the NSObject wrapper.
Your first paragraph is only true under the following conditions :
1. If the wrapper objects themselves have underlying managed resources to
dispose.
(a. If all the managed dealloc implementation does is call the native
one, it has no meanning, does it ?)
(b. At least for NSProxy and NSObject, I don't remember noticing any
underlying resources needing explicit disposal (pure wrappers)).
2. If there is no reference to a certain NSObject managed wrapper
instance anywhere in user code, it should be collected by GC whether or not
the
native instance is still alive. on the flip side - deallocation of the
native instances themselves - The fact that the framework caches these
instances
seems to me more like buggy overhead than a performance gain, can this
be opened for public discussion ?
3. And most importantly - instantiation of a managed wrapper should only be
performed for an object that the user code has _explicitly_ exposed to
.net user code. Correct me if I'm wrong but why should a managed
instance be created for a native instance of ALL native NSObjects,
NSProxies,
and the other NS classes that have managed wrapper definitions in the
Monobjc framework...
Regarding your second and third paragraphs - I noticed hangs (deadlocks in
the main UI thread) and crashes that were related to NSObject dealloc as
well. I'll try to recreate something that brings the problem to visible
view, although I'm not sure it'll be that simple...
p.s.
In the documentation you referenced, (bridging topic in monobjc site), the
following is stated :
An Objective-C object is wrapped in a managed wrapper only if it is
> referenced in .NET code. This limits the amount of managed wrappers in .NET
> runtime.
>
This entire thread exists due to the fact that this seems not to be true...
(i.e. webkit objects, appkit objects, foundations objects that were never
referenced by .net code seem to have wrappers created for them)...
On Wed, Dec 24, 2008 at 2:05 PM, Laurent Etiemble <
[email protected]> wrote:
> Hello,
>
> In order to correctly bridge the Objective-C instance lifecycle, Monobjc
> inserts itself in the dealloc message hierarchy (see
> http://www.monobjc.net/index.php?page=bridging). This way, Monobjc
> intercepts all dealloc messages, removes any existing managed wrapper, and
> then pass the dealloc message to the original implementation. This trick is
> called method swizzling (as used by Cocoa in Bindings); see
> http://www.cocoadev.com/index.pl?MethodSwizzling for details.
>
> It seems overkill that ALL dealloc messages are to be intercepted, but I
> think this is the only way to synchronize native deallocation and managed
> wrapper disposal.
>
> As far as I know, there was no report of error for the NSObject hierarchy.
> But for the NSProxy hierarchy, I am not 100% confident about the trick.
>
> Can you attach a sample application that contains only the offending part
> so I can reproduce and investigate ?
>
> Regards, Laurent Etiemble.
>
> 2008/12/23 yoni shalom <[email protected]>
>
> I have an application that uses monobjc, embedded under a Cocoa app.
>> I have witnessed various timing/threading issues (.net exceptions, SIGSEGV
>> | EXC_BAD_ACCESS signals etc) with variouse stacks, for example :
>>
>> [NSRunloop run] //beginning
>> ... //some framework code
>> ...
>> [NSDistantObject dealloc]
>> ??
>> ?? //.net JIT compiled function addresses - the .net
>> wrappers for NSObject dealloc, or NSProxy dealloc
>> ??
>> [NSProxy isKindOfClass]
>> ... //some native forwarding...
>> ...
>> [SIGSEGV handler / native exception handler]
>>
>> I'm attaching a real example at the end of this post.
>> some facts :
>>
>> 1. The object for which the wrapper-dealloc is called on is NOT A .Net
>> monobjc NSObject ! Are all objective-c native objects becoming "wrapped"
>> just because we are using Monobjc ?
>> 2. If the answer to the previous question is Yes (as it seems from my
>> debugging session), I personally see it as a major flaw - bugs in monobjc
>> shouldn't affect objects which the developer never intended to instanciate
>> .Net managed wrappers for.
>>
>> 3. The code in the dealloc wrapper causes induces the use of
>> Monitor.Enter, which in some occasions causes deadlocks (couldn't figure out
>> why, didn't bother on debugging)
>> 4. The code in the dealloc wrapper may run AFTER the native ptr is no
>> longer valid for some reason, causing the native call to [self dealloc] to
>> crash and burn with all kinds of nasty signals and shit.
>>
>> Removing the function "dealloc" in NSObject and NSProxy wrappers problems
>> I've been trying to solve for two days.
>> This, again, despite the fact that the objects causing the problem in the
>> stack are not .net instances related to my managed embedded stack!, they are
>> just regular, native, objective-c objects!
>>
>>
>> A real example (crash report), in which u see WebKit (WebView embedded in
>> my app) trying to release an object (note the command on line 10):
>>
>> Thread 0 Crashed:
>> 0 libSystem.B.dylib 0x96f45b9e __kill + 10
>> 1 libSystem.B.dylib 0x96fbcec2 raise + 26
>> 2 libSystem.B.dylib 0x96fcc47f abort + 73
>> 3 libmono.0.0.0.dylib 0x0078e999 mono_handle_native_sigsegv
>> + 215 (mini-exceptions.c:1366)
>> 4 libmono.0.0.0.dylib 0x00730ece sigsegv_signal_handler +
>> 226 (mini.c:13441)
>> 5 libSystem.B.dylib 0x96f4409b _sigtramp + 43
>> 6 ??? 0xffffffff 0 + 4294967295
>> 7 com.apple.CoreFoundation 0x921156bd ___forwarding___ + 237
>> 8 com.apple.CoreFoundation 0x92115a12 _CF_forwarding_prep_0 + 50
>> 9 com.apple.Foundation 0x937485a0 -[NSProxy isKindOfClass:] +
>> 160
>> 10 ??? 0x0304d567 0 + 50648423 // ---->
>> somewhere along the ?? functions is Monobjc, trying to execute the managed
>> wrapper function NSProxy.Dealloc()!
>> 11 ??? 0x16d00436 0 + 382731318
>> 12 ??? 0x16d0021e 0 + 382730782
>> 13 ??? 0x16d001ac 0 + 382730668
>> 14 ??? 0x02ad0bfa 0 + 44895226
>> 15 com.apple.Foundation 0x93708695 -[NSDistantObject dealloc]
>> + 117
>> 16 com.apple.CoreFoundation 0x9202c823 CFBagApplyFunction + 131
>> 17 com.apple.Foundation 0x93748094 invalidateConnection + 596
>> 18 com.apple.Foundation 0x93747815 -[NSConnection invalidate]
>> + 613
>> 19 com.apple.Foundation 0x93740238 +[NSConnection
>> _portInvalidated:] + 712
>> 20 com.apple.Foundation 0x936c91da _nsnote_callback + 106
>> 21 com.apple.CoreFoundation 0x92077aba __CFXNotificationPost + 362
>> 22 com.apple.CoreFoundation 0x92077d93
>> _CFXNotificationPostNotification + 179
>> 23 com.apple.Foundation 0x936c6440 -[NSNotificationCenter
>> postNotificationName:object:userInfo:] + 128
>> 24 com.apple.Foundation 0x93711c7a _NSPortDeathNotify + 106
>> 25 com.apple.CoreFoundation 0x920723eb CFMachPortInvalidate + 219
>> 26 com.apple.CoreFoundation 0x92072de6 __CFNotifyDeadMachPort +
>> 294
>> 27 com.apple.CoreFoundation 0x92072635 __CFMachPortPerform + 117
>> 28 com.apple.CoreFoundation 0x92096908 CFRunLoopRunSpecific + 3896
>> 29 com.apple.CoreFoundation 0x92096cf8 CFRunLoopRunInMode + 88
>> 30 com.apple.Foundation 0x93750ef0 -[NSConcreteTask
>> waitUntilExit] + 128
>> 31 com.myapp.plugin 0x17207c79 -[plugin waitUntilExit] + 89
>> (plugin.m:150)
>> 32 com.myapp.plugin 0x17207a31 -[plugin stop] + 93
>> (plugin.m:87)
>> 33 com.myapp.plugin 0x1720700b -[plugin(scripting)
>> stopPlayback] + 164 (plugin.m:47)
>> 34 com.myapp.plugin 0x17206eac -[plugin(scripting) url:] +
>> 43 (plugin.m:30)
>> 35 com.apple.CoreFoundation 0x92115a7d __invoking___ + 29
>> 36 com.apple.CoreFoundation 0x92115468 -[NSInvocation invoke] +
>> 136
>> 37 com.apple.JavaScriptCore 0x90b70cfd
>> KJS::Bindings::ObjcInstance::invokeMethod(KJS::ExecState*,
>> WTF::Vector<KJS::Bindings::Method*, 0ul> const&, KJS::List const&) + 397
>> 38 com.apple.JavaScriptCore 0x90b66646
>> KJS::RuntimeMethod::callAsFunction(KJS::ExecState*, KJS::JSObject*,
>> KJS::List const&) + 278
>> 39 com.apple.JavaScriptCore 0x90b2ddd6
>> KJS::FunctionCallDotNode::evaluate(KJS::ExecState*) + 806
>> 40 com.apple.JavaScriptCore 0x90b34329
>> KJS::ExprStatementNode::execute(KJS::ExecState*) + 25
>> 41 com.apple.JavaScriptCore 0x90b3b340
>> KJS::BlockNode::execute(KJS::ExecState*) + 64
>> 42 com.apple.JavaScriptCore 0x90b472fa
>> KJS::IfElseNode::execute(KJS::ExecState*) + 106
>> 43 com.apple.JavaScriptCore 0x90b56490
>> KJS::CaseBlockNode::executeBlock(KJS::ExecState*, KJS::JSValue*) + 688
>> 44 com.apple.JavaScriptCore 0x90b5618f
>> KJS::SwitchNode::execute(KJS::ExecState*) + 79
>> 45 com.apple.JavaScriptCore 0x90b34a71
>> KJS::FunctionBodyNode::execute(KJS::ExecState*) + 481
>> 46 com.apple.JavaScriptCore 0x90b34529
>> KJS::FunctionImp::callAsFunction(KJS::ExecState*, KJS::JSObject*, KJS::List
>> const&) + 265
>> 47 com.apple.JavaScriptCore 0x90b2ddd6
>> KJS::FunctionCallDotNode::evaluate(KJS::ExecState*) + 806
>> 48 com.apple.JavaScriptCore 0x90b34329
>> KJS::ExprStatementNode::execute(KJS::ExecState*) + 25
>> 49 com.apple.JavaScriptCore 0x90b3b340
>> KJS::BlockNode::execute(KJS::ExecState*) + 64
>> 50 com.apple.JavaScriptCore 0x90b342ce
>> KJS::IfNode::execute(KJS::ExecState*) + 78
>> 51 com.apple.JavaScriptCore 0x90b34a71
>> KJS::FunctionBodyNode::execute(KJS::ExecState*) + 481
>> 52 com.apple.JavaScriptCore 0x90b34529
>> KJS::FunctionImp::callAsFunction(KJS::ExecState*, KJS::JSObject*, KJS::List
>> const&) + 265
>> 53 com.apple.JavaScriptCore 0x90b2ddd6
>> KJS::FunctionCallDotNode::evaluate(KJS::ExecState*) + 806
>> 54 com.apple.JavaScriptCore 0x90b34329
>> KJS::ExprStatementNode::execute(KJS::ExecState*) + 25
>> 55 com.apple.JavaScriptCore 0x90b3b340
>> KJS::BlockNode::execute(KJS::ExecState*) + 64
>> 56 com.apple.JavaScriptCore 0x90b472fa
>> KJS::IfElseNode::execute(KJS::ExecState*) + 106
>> 57 com.apple.JavaScriptCore 0x90b34a71
>> KJS::FunctionBodyNode::execute(KJS::ExecState*) + 481
>> 58 com.apple.JavaScriptCore 0x90b34529
>> KJS::FunctionImp::callAsFunction(KJS::ExecState*, KJS::JSObject*, KJS::List
>> const&) + 265
>> 59 com.apple.JavaScriptCore 0x90b2ddd6
>> KJS::FunctionCallDotNode::evaluate(KJS::ExecState*) + 806
>> 60 com.apple.JavaScriptCore 0x90b34329
>> KJS::ExprStatementNode::execute(KJS::ExecState*) + 25
>> 61 com.apple.JavaScriptCore 0x90b34a71
>> KJS::FunctionBodyNode::execute(KJS::ExecState*) + 481
>> 62 com.apple.JavaScriptCore 0x90b34529
>> KJS::FunctionImp::callAsFunction(KJS::ExecState*, KJS::JSObject*, KJS::List
>> const&) + 265
>> 63 com.apple.JavaScriptCore 0x90b2ddd6
>> KJS::FunctionCallDotNode::evaluate(KJS::ExecState*) + 806
>> 64 com.apple.JavaScriptCore 0x90b34329
>> KJS::ExprStatementNode::execute(KJS::ExecState*) + 25
>> 65 com.apple.JavaScriptCore 0x90b34a71
>> KJS::FunctionBodyNode::execute(KJS::ExecState*) + 481
>> 66 com.apple.JavaScriptCore 0x90b34529
>> KJS::FunctionImp::callAsFunction(KJS::ExecState*, KJS::JSObject*, KJS::List
>> const&) + 265
>> 67 com.apple.JavaScriptCore 0x90b788b7
>> KJS::JSObject::call(KJS::ExecState*, KJS::JSObject*, KJS::List const&) + 135
>> 68 com.apple.WebCore 0x928474ee
>> WebCore::JSAbstractEventListener::handleEvent(WebCore::Event*, bool) + 1390
>> 69 com.apple.WebCore 0x927a3846
>> WebCore::EventTarget::handleLocalEvents(WebCore::EventTargetNode*,
>> WebCore::Event*, bool) + 182
>> 70 com.apple.WebCore 0x927a376f
>> WebCore::EventTargetNode::handleLocalEvents(WebCore::Event*, bool) + 79
>> 71 com.apple.WebCore 0x927a3206
>> WebCore::EventTarget::dispatchGenericEvent(WebCore::EventTargetNode*,
>> WTF::PassRefPtr<WebCore::Event>, int&, bool) + 454
>> 72 com.apple.WebCore 0x927a2f4f
>> WebCore::EventTargetNode::dispatchEvent(WTF::PassRefPtr<WebCore::Event>,
>> int&, bool) + 255
>> 73 com.apple.WebCore 0x92960c1d
>> WebCore::EventTargetNode::dispatchMouseEvent(WebCore::AtomicString const&,
>> int, int, int, int, int, int, bool, bool, bool, bool, bool, WebCore::Node*,
>> WTF::PassRefPtr<WebCore::Event>) + 509
>> 74 com.apple.WebCore 0x929609d5
>> WebCore::EventTargetNode::dispatchMouseEvent(WebCore::PlatformMouseEvent
>> const&, WebCore::AtomicString const&, int, WebCore::Node*) + 165
>> 75 com.apple.WebCore 0x929604d5
>> WebCore::EventHandler::dispatchMouseEvent(WebCore::AtomicString const&,
>> WebCore::Node*, bool, int, WebCore::PlatformMouseEvent const&, bool) + 101
>> 76 com.apple.WebCore 0x928d21c2
>> WebCore::EventHandler::handleMouseReleaseEvent(WebCore::PlatformMouseEvent
>> const&) + 722
>> 77 com.apple.WebCore 0x928d1df9
>> WebCore::EventHandler::mouseUp(NSEvent*) + 393
>> 78 com.apple.WebKit 0x90a698bc -[WebHTMLView mouseUp:] +
>> 220
>> 79 com.apple.AppKit 0x95e59809 -[NSWindow sendEvent:] +
>> 5539
>> 80 com.apple.AppKit 0x95e26311 -[NSApplication sendEvent:]
>> + 2941
>> 81 com.apple.AppKit 0x95d83d0f -[NSApplication run] + 847
>> 82 com.apple.AppKit 0x95d50f14 NSApplicationMain + 574
>> 83 com.MyApp 0x00002ebb main + 133 (main.m:22)
>> 84 com.MyApp 0x00002e0a start + 54
>>
>
>