Re: Need advice: Object ownership and threading issue, causing a rare crash.
Re: Need advice: Object ownership and threading issue, causing a rare crash.
- Subject: Re: Need advice: Object ownership and threading issue, causing a rare crash.
- From: Motti Shneor <email@hidden>
- Date: Tue, 07 May 2013 01:26:11 +0300
Hello Ken, and so-many-thanks for the information.
On 4 במאי 2013, at 07:24, Ken Thomases <email@hidden> wrote:
> On May 2, 2013, at 11:53 AM, Jens Alfke wrote:
>
>> On May 1, 2013, at 5:10 AM, Motti Shneor <email@hidden> wrote:
>>
>>> Currently, MyB retains itself within its thread, and releases itself just before the thread exits. I know it is bad practice (self retaining objects), but I did not yet think of a better way.
>>>
>>> This way, when the owner releases its MyB and replaces its reference with a new MyB object, the MyB is just released once, and does not get deallocated. When its thread finishes its cycle in the background, the thread function releases the objects again, and returns.
>>
>> That's fine, IMHO, and I've both read and written code that does this.
>
> I agree. And Cocoa's -[NSObject performSelectorInBackground:withObject:] and +[NSThread detachNewThreadSelector:toTarget:withObject:] retain the target and argument objects for the lifetime of the thread. The releases occur on the background thread because there's really no other way. The same happens with asynchronously dispatched blocks and the objects they retain.
I wonder how I missed this so-relevant-info until now. Shame on me.... I use +[NSThread detachNewThreadSelector:toTarget:withObject:] and thus I may remove my [self retain] and [self release] altogether!
>
>
> In other words, what you've done (as you've described it), is not at all unusual.
Actually streamlined with NSThread's usage intent. Makes me feel better about this implementation.
>
> If you're concerned about your implementation, you should probably use the Cocoa methods to manage the thread and have it handle memory management for you.
>
I do --- that's the weird thing about it. I'm using +[NSThread detachNewThreadSelector:toTarget:withObject:] which does the same thing I intended to do, which is just fine.
>
> On May 1, 2013, at 7:10 AM, Motti Shneor wrote:
>
>> This seems to be OK --- but in rare cases the program crashes trying to REENTER the "dealloc" of MyB!!!! It seems that the actual "release" method gets called both from the thread context and the main thread's context.
>
> The -[NSObject release] method is thread-safe. Multi-threaded Cocoa programming would be infeasible otherwise. You haven't overridden it and implemented your own have you?
>
Nope. No override of "release" in the whole huge app.
> Honestly, I doubt that -dealloc is reentered. I suspect you've misdiagnosed what is happening or, perhaps, there's some other severe problem such as heap corruption that's leading to that. It *definitely* won't happen merely because two threads are racing in -release for the same object (assuming they are both entitled to release the object because they each have an ownership stake).
Well, the crash-log provides a call-stack which quite clearly shows the "dealloc" re-enrered. Now I'm really puzzled, because if NSThread protected me against premature deallocation on its own, How on earth could I reach the "dealloc" before the thread was done?
>
>> What's the best way to get out of this? How can I simply synchronize the "release" calls, without blocking both threads? Maybe I should restrict myself to retaining/releasing in the main thread only? Is there some syntactic Obj-C sugar to ease such things?
>
> There's no way to do so and no need.
OK --- I wont :)
Thanks again.
>
> Regards,
> Ken
>
Motti Shneor
----------------------------------------
Ceterum censeo Microsoftinem delendam esse
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden