From: Alex P. <pes...@ma...> - 2011-03-28 07:36:58
|
On 03/27/11 19:55, Adriano dos Santos Fernandes wrote: > On 27-03-2011 09:57, Alex Peshkoff wrote: >> On 03/25/11 21:16, Adriano dos Santos Fernandes wrote: >>>> Let's suppose that user implemented some helper around IAttachment*, >>>> which is not refCounted as you wish. Please explain, how must behave >>>> that object when detach is requested, but there are some other threads, >>>> using that object. >>>> >>> Let me first say something about your refcounted approach: >>> >>> Current, when an user detachs and attachment, all handles related to it >>> and not-yet-freed are closed. >>> >>> Let say you did the same when calling IAttachment::detach. Then your >>> refcount don't work, cause it will wipe pointers to objects with references. >>> >>> Let say it don't free the subobjects. Then you're making a common >>> situation (close a parent -> close children) to leak memory. >>> >>> Now about your question, more directly. If this thread is doing >>> something inside the yvalve, the detach may (*internally) decrement a >>> refcounter and don't free the object, so we don't see a crash inside the >>> yvalve. As soon the yvalve release this reference, the object is wiped. >> This is wrong suggestion. We must return correct status value from >> detach, but what can we return if we just decrement refcounter? And what >> should we do when we try to do real job, but something goes wrong? >> This is specially well seen on a sample with commit and some error >> thrown when doing DFW. >> > No, Alex. We don't delay the detach in the provider object. We delay > "delete this" on the yvalve object. And since the user access always via > the yvalve object, the refcounting on the provider object becomes > unnecessary too. > But such behavior can cause races. Suppose attachment helper is used by 2 threads. One wants to access it, checks for object's presence, and copies pointer to IAttachment into the register (it's needed at least to access VTable). At this moment thread gets swapped from CPU by OS scheduler. Another thread performs detach and the pointer (already copied into the register) becomes invalid. But when first thread gets control it does not know that pointer became invalid - and segfault happens. Be sure - this is not just theory. It happens in 2.5 when it's attempted to be shutdown under very high load, and races in yvalve take more time than unallocated block stays in memory pool cache. IMO we should fix this at least in FB3. Certainly, more clever helper object can solve a problem. But I do not see a way to build it without lock. And I claim that this is too high price for removing reference counters from API. >> Another approach that will sooner of all work is when >> detach/drop/commit/etc do not dispose/release an object. This must be >> done explicitly, i.e. the sequence of calls is: >> >> ITransaction* tra = att->startTransaction(); >> // do some job with that transaction >> tra->commit(); >> tra->dispose(); >> >> This works, but looks bad for ST appliactions. >> > Don't think this is ok. We need dispose for things who only need > dispose, and we don't need it in objects that must be freed by another ways. > Having dispose is also a way to avoid races when detach() happens. But I prefer reference counters. |