mgmt: fix InternalFace::processInterest crash when Interest is gone

Interest may be satisfied by Notification and be removed from PIT
between sendInterest and processInterest.

refs #1452

Change-Id: I0c3e05c34f0d8607d96dcfd156a3e87c1ecb26f2
diff --git a/daemon/mgmt/internal-face.cpp b/daemon/mgmt/internal-face.cpp
index 51af45b..de77009 100644
--- a/daemon/mgmt/internal-face.cpp
+++ b/daemon/mgmt/internal-face.cpp
@@ -42,13 +42,22 @@
 
   // Invoke .processInterest a bit later,
   // to avoid potential problems in forwarding pipelines.
+  weak_ptr<const Interest> interestWeak = interest.shared_from_this();
   getGlobalIoService().post(bind(&InternalFace::processInterest,
-                                 this, boost::cref(interest)));
+                                 this, interestWeak));
 }
 
 void
-InternalFace::processInterest(const Interest& interest)
+InternalFace::processInterest(weak_ptr<const Interest> interestWeak)
 {
+  shared_ptr<const Interest> interestPtr = interestWeak.lock();
+  if (!static_cast<bool>(interestPtr)) {
+    // Interest is gone because it's satisfied and removed from PIT
+    NFD_LOG_DEBUG("processInterest: Interest is gone");
+    return;
+  }
+  const Interest& interest = *interestPtr;
+
   if (m_interestFilters.size() == 0)
     {
       NFD_LOG_DEBUG("no Interest filters to match against");
diff --git a/daemon/mgmt/internal-face.hpp b/daemon/mgmt/internal-face.hpp
index 416850c..479f256 100644
--- a/daemon/mgmt/internal-face.hpp
+++ b/daemon/mgmt/internal-face.hpp
@@ -78,7 +78,7 @@
 
 private:
   void
-  processInterest(const Interest& interest);
+  processInterest(weak_ptr<const Interest> interestWeak);
 
 private:
   std::map<Name, OnInterest> m_interestFilters;
diff --git a/tests/mgmt/fib-manager.cpp b/tests/mgmt/fib-manager.cpp
index f2d059a..0e2e8c0 100644
--- a/tests/mgmt/fib-manager.cpp
+++ b/tests/mgmt/fib-manager.cpp
@@ -239,13 +239,13 @@
 {
   shared_ptr<InternalFace> face = getInternalFace();
 
-  Interest command("/localhost/nfd/fib");
+  shared_ptr<Interest> command = makeInterest("/localhost/nfd/fib");
 
   face->onReceiveData +=
     bind(&FibManagerFixture::validateControlResponse, this,  _1,
-         command.getName(), 400, "Malformed command");
+         command->getName(), 400, "Malformed command");
 
-  face->sendInterest(command);
+  face->sendInterest(*command);
   g_io.run_one();
 
   BOOST_REQUIRE(didCallbackFire());
diff --git a/tests/mgmt/internal-face.cpp b/tests/mgmt/internal-face.cpp
index 6bd63d1..595f05f 100644
--- a/tests/mgmt/internal-face.cpp
+++ b/tests/mgmt/internal-face.cpp
@@ -134,8 +134,8 @@
   // we hit the end of the std::map
 
   Name commandName("/localhost/nfd/fib/end");
-  Interest command(commandName);
-  face->sendInterest(command);
+  shared_ptr<Interest> command = makeInterest(commandName);
+  face->sendInterest(*command);
   g_io.run_one();
 
   BOOST_REQUIRE(didOnInterestFire());
@@ -157,8 +157,8 @@
   // we hit the beginning of the std::map
 
   Name commandName("/localhost/nfd");
-  Interest command(commandName);
-  face->sendInterest(command);
+  shared_ptr<Interest> command = makeInterest(commandName);
+  face->sendInterest(*command);
   g_io.run_one();
 
   BOOST_REQUIRE(didNoOnInterestFire() == false);
@@ -186,8 +186,8 @@
   // /localhost/nfd/fib
 
   Name commandName("/localhost/nfd/fib");
-  Interest command(commandName);
-  face->sendInterest(command);
+  shared_ptr<Interest> command = makeInterest(commandName);
+  face->sendInterest(*command);
   g_io.run_one();
 
   BOOST_REQUIRE(didOnInterestFire());
@@ -212,14 +212,24 @@
   // an Interest filter
 
   Name commandName("/localhost/nfd/fib/previous");
-  Interest command(commandName);
-  face->sendInterest(command);
+  shared_ptr<Interest> command = makeInterest(commandName);
+  face->sendInterest(*command);
   g_io.run_one();
 
   BOOST_REQUIRE(didOnInterestFire());
   BOOST_REQUIRE(didNoOnInterestFire() == false);
 }
 
+BOOST_AUTO_TEST_CASE(InterestGone)
+{
+  shared_ptr<InternalFace> face = make_shared<InternalFace>();
+  shared_ptr<Interest> interest = makeInterest("ndn:/localhost/nfd/gone");
+  face->sendInterest(*interest);
+
+  interest.reset();
+  BOOST_CHECK_NO_THROW(g_io.poll());
+}
+
 BOOST_AUTO_TEST_SUITE_END()
 
 } // namespace tests