Bug #2177
closedINVALID_FACE_ID appears in FIB
100%
Description
Steps to reproduce:
- start NFD
- run this code snippet:
#include <ndn-cxx/face.hpp>
using namespace ndn;
int main(int argc, char** argv)
{
Face face;
for (int i = 0; i < 300; ++i) {
Name prefix("/localhost/app");
prefix.appendVersion(i);
face.registerPrefix(prefix,
bind([i] { std::cout << "SUCCESS " << i << std::endl; }),
bind([i] { std::cout << "FAILURE " << i << std::endl; })
);
}
face.processEvents();
}
- press CTRL+C to kill the program in step 2
- look at FIB with
nfd-status -b
Expected: prefixes registered by the program are erased
Actual: /localhost/app/%FD%BC nexthops={faceid=18446744073709551615 (cost=0)}
Updated by Junxiao Shi about 10 years ago
- Has duplicate Bug #1812: INVALID_FACE_ID appears in FIB added
Updated by Vince Lehman about 10 years ago
I'm not sure of the cause but it looks like there is an issue with something called in "Fib::removeNextHopFromAllEntries".
If you add these debug messages to the code:
void
Fib::removeNextHopFromAllEntries(shared_ptr<Face> face)
{
for (NameTree::const_iterator it = m_nameTree.fullEnumerate(
&predicate_NameTreeEntry_hasFibEntry); it != m_nameTree.end();) {
shared_ptr<fib::Entry> entry = it->getFibEntry();
++it; // advance the iterator before `erase` invalidates it
std::cout << "Before " << entry->getPrefix() << ": " << entry->getNextHops().size() << std::endl;
entry->removeNextHop(face);
std::cout << "After " << entry->getPrefix() << ": " << entry->getNextHops().size() << std::endl;
if (!entry->hasNextHops()) {
this->erase(*entry);
}
}
std::cout << "After NextHop removal" << std::endl;
for (NameTree::const_iterator it = m_nameTree.fullEnumerate(&predicate_NameTreeEntry_hasFibEntry);
it != m_nameTree.end(); ++it)
{
shared_ptr<fib::Entry> entry = it->getFibEntry();
std::cout << entry->getPrefix() << ": " << entry->getNextHops().size() << std::endl;
}
}
You get:
...
Before /localhost/app/%FD%04: 1
After /localhost/app/%FD%04: 0
Before /localhost/app/%FD%01%24: 1
After /localhost/app/%FD%01%24: 0
After NextHop removal
/localhost/app/%FD%CD: 1
/localhost/app/%FDc: 1
/localhost/app/%FDS: 1
/localhost/app/%FD%A9: 1
/localhost/app/%FD%01: 1
/localhost/app/%FD%1D: 1
/localhost/app/%FDH: 1
...
So, it looks like the nexthops are not being removed and an invalid face is assigned to them by the FaceTable:
void
FaceTable::remove(shared_ptr<Face> face)
{
...
face->setId(INVALID_FACEID);
...
m_forwarder.getFib().removeNextHopFromAllEntries(face);
}
Updated by Lan Wang about 10 years ago
Alex/Junxiao: who's the right person to fix this problem?
Updated by Junxiao Shi about 10 years ago
It's too early to talk about assignment. We need to know the cause of this problem before deciding who to assign.
Updated by Lan Wang about 10 years ago
Can whoever wrote the code mentioned in note 2 figure out the problem?
Updated by Junxiao Shi about 10 years ago
- Assignee set to Junxiao Shi
I'll investigate this problem.
Since it doesn't affect normal applications that register only a few prefixes, this is not urgent.
Updated by Junxiao Shi about 10 years ago
- Status changed from New to In Progress
- % Done changed from 0 to 20
This Bug is due to Fib::removeNextHopFromAllEntries
's incorrect usage of NameTree
iterators.
NameTree full enumeration iterators may be invalidated whenever there is a NameTree entry insertion or deletion.
Full enumeration iterators are tied to buckets, but an insertion or deletion may cause NameTree to resize its hashtable, where nodes are rehashed into new buckets.
This can be confirmed by observing that this->size()
at the top of Fib::removeNextHopFromAllEntries
differs from the number of loop body executions.
Updated by Junxiao Shi about 10 years ago
- Status changed from In Progress to Code review
- % Done changed from 20 to 100
Updated by Junxiao Shi about 10 years ago
- Status changed from Code review to Closed