BIND 10 #2836: update in-memory zone loading so it can work with shmem segment
BIND 10 Development
do-not-reply at isc.org
Wed May 15 18:06:35 UTC 2013
#2836: update in-memory zone loading so it can work with shmem segment
-------------------------------------+-------------------------------------
Reporter: jinmei | Owner:
Type: task | jinmei
Priority: medium | Status:
Component: data source | reviewing
Keywords: | Milestone:
Sensitive: 0 | Sprint-20130528
Sub-Project: DNS | Resolution:
Estimated Difficulty: 4 | CVSS Scoring:
Total Hours: 0 | Defect Severity: N/A
| Feature Depending on Ticket:
| shared memory data source
| Add Hours to Ticket: 0
| Internal?: 0
-------------------------------------+-------------------------------------
Comment (by jinmei):
Replying to [comment:20 vorner]:
> > > I also pushed the test that crashes for me. Does it crash for you
too? Does valgrind work for you? If so, could you run it through it?
> >
> > That test crashed in my environment, too (though in a different place
> > of the code). I've found one issue and committed a fix to that (my)
> > problem at 575854a507052ad7de51aa259fd5d8f04156d15d on branch
> > trac2836-2. Hopefully it will fix yours, too. Note that we may or
> > may not use the 5758... fix as it is (see below).
>
> I incorporated changes inspired by yours, and the separate set as well.
The test now passes, so I hope it works as it should. But I'm still not
100% sure there's no other bug like this.
There still seem to be a few subtle cases as pointed out below, but
I'm now getting quite sure it's much safer thanks to the revised
version of `SegmentObjectHolder`.
> > - depending on how we revise `SegmentObjectHolder`, `result.zone_data`
> > could also be relocated on return of `addZone`.
>
> I don't see how that could happen or how to protect against that. Can
you explain where it would relocate?
It now shouldn't happen. Previously the construction of
`SegmentObjectHolder` could have caused relocation, and `addZone()`
could still return successfully. Now it doesn't happen as the
constructor throws in that case. See also below.
> IMO this should be all the functionality for the branch. Or I hope so.
Many thanks for pointing me to the problem of the test.
It now looks almost ready. I have a few less critical points to
adjust (mostly for documentation and cleanups):
'''others'''
- I made a few minor changes as usual.
- Among them is a build fix regarding `USE_SHARED_MEMORY` (d35ac0a).
This also suggest you might want to check if the branch can build
and pass tests `--without-shared-memory` (once again, even if you've
done that once)
- I suggest clarifying exception/relocation safety in various
create() methods. For example, for `ZoneData::create()`,
{{{#!cpp
/// \brief Allocate and construct \c ZoneData.
///
/// This method ensures there'll be no memory leak on exception.
/// But addresses allocated from \c mem_sgmt could be relocated if
/// \c util::MemorySegmentGrown is thrown; the caller or its upper
layer
/// must be aware of that possibility and update any such addresses
/// accordingly. On successful return, this method ensures there's no
/// address relocation.
///
/// \throw util::MemorySegmentGrown memory segment has grown, possibly
/// causing address relocation.
/// \throw std::bad_alloc Memory allocation fails.
}}}
I believe this generally applies to `NSEC3Data::create()`,
`ZoneTable::create()`, `ZoneTable::addZone()` and `RdataSet::create()`.
'''segment_object_holder.h'''
- I'm afraid the relationship between the constructor and set is not
obvious and requires explanation. I'd suggest adding the following
note as a comment:
{{{#!cpp
// more simplified.
//
// Note, however, that it doesn't take the pointer to hold on
construction.
// This is because the constructor itself can throw or cause address
// reallocation inside the memory segment. If that happens various
// undesirable effects can happen, such as memory leak or unintentional
access
// to the pre-reallocated address. To make it safer, we use a separate
// \c set() method, which is exception free and doesn't cause address
// reallocation. So the typical usage is to first construct the holder
// object, immediately followed by a call to \c set(). Subsequent access
// to the held address should be done via the \c get() method. get()
ensures
// the address is always valid in the memory segment even if address
// reallocation happens between set() and get().
//
// template parameter T is the type of object allocated by mem_sgmt.
}}}
'''zone_data_updater.cc'''
- We shouldn't need this hack anymore thanks to the revised
`SegmentObjectHolder`:
{{{#!cpp
// The create above might have relocated data. So get it again,
// just to make sure.
zone_data_ =
static_cast<ZoneData*>(mem_sgmt_.
getNamedAddress("updater_zone_data").
second);
}}}
(see also the suggested doc update for xxx:create() above).
Previously the construction of `SegmentObjectHolder` itself could
cause relocation, which was the reason for the crash and the need
for this hack. Now it shouldn't happen (instead `MemorySegmentGrown`
will be thrown, which will be handled at an appropriate upper
layer).
'''zone_data_updater.h'''
- there's a slight chance that `zone_data_` is relocated here:
{{{#!cpp
mem_sgmt_.setNamedAddress("updater_zone_data", zone_data_);
}}}
so we'll need to make sure it's the latest:
{{{#!cpp
mem_sgmt_.setNamedAddress("updater_zone_data", zone_data_);
zone_data_ =
mem_sgmt_.getNamedAddress("updater_zone_data"_).second;
assert(zone_data_);
}}}
'''zone_writer.cc'''
- load(): it's probably safer to call `resetHeader` immediately after
`load_action_`:
{{{#!cpp
zone_data_ = load_action_(segment_.getMemorySegment());
segment_.resetHeader(); // header may have been relocated
if (!zone_data_) {
// Bug inside load_action_.
isc_throw(isc::InvalidOperation, "No data returned from load
action");
}
}}}
- install: we should move the call to `resetHeader` in the catch
block:
{{{#!cpp
} catch (const isc::util::MemorySegmentGrown&) {
segment_.resetHeader();
}
}}}
and there's now no need for calling it at the end of the method,
because addZone() ensures no relocation on successful return
(see above).
--
Ticket URL: <http://bind10.isc.org/ticket/2836#comment:21>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list