void UdpFace::closeIfIdle() { // Face can be switched from on-demand to non-on-demand mode // (non-on-demand -> on-demand transition is not allowed) if (this->getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) { if (!hasBeenUsedRecently()) { NFD_LOG_FACE_INFO("Closing for inactivity"); close(); // #1718 manual test: uncomment, run NFD in valgrind, send in a UDP packet // expect read-after-free error and crash // getGlobalIoService().post([this] { // NFD_LOG_FACE_ERROR("Remaining references: " << this->shared_from_this().use_count()); // }); } else { resetRecentUsage(); m_lastIdleCheck = time::steady_clock::now(); m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, bind(&UdpFace::closeIfIdle, this)); } } // else do nothing and do not reschedule the event }
void UnicastUdpTransport::scheduleClosureWhenIdle() { m_closeIfIdleEvent = scheduler::schedule(m_idleTimeout, [this] { if (!hasBeenUsedRecently()) { NFD_LOG_FACE_INFO("Closing due to inactivity"); this->close(); } else { resetRecentUsage(); scheduleClosureWhenIdle(); } }); setExpirationTime(time::steady_clock::now() + m_idleTimeout); }
ndn::nfd::FaceStatus UdpFace::getFaceStatus() const { auto status = DatagramFace::getFaceStatus(); if (this->getPersistency() == ndn::nfd::FACE_PERSISTENCY_ON_DEMAND) { time::milliseconds left = m_idleTimeout; left -= time::duration_cast<time::milliseconds>(time::steady_clock::now() - m_lastIdleCheck); if (left < time::milliseconds::zero()) left = time::milliseconds::zero(); if (hasBeenUsedRecently()) left += m_idleTimeout; status.setExpirationPeriod(left); } return status; }