From 0c52d1ade62a01aa8b2046e2c4dc40afd5dbe04a Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Wed, 22 May 2019 18:31:53 +0200 Subject: [PATCH] Addl loop prevention for traverse_parent_state (#1414) * Addl loop prevention for traverse_parent_state Add some additional ways to prevent potential loops when traversing parent state: - If the slow threadinfo ever has a tid of -1, stop. - If the slow threadinfo ever has ptid == tid, declare a loop and stop. * Add more info to loop warning. Include current pointer's tid/ptid. --- userspace/libsinsp/threadinfo.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/userspace/libsinsp/threadinfo.cpp b/userspace/libsinsp/threadinfo.cpp index 0264f14962..cf9615c737 100644 --- a/userspace/libsinsp/threadinfo.cpp +++ b/userspace/libsinsp/threadinfo.cpp @@ -904,7 +904,8 @@ void sinsp_threadinfo::traverse_parent_state(visitor_func_t &visitor) // Move fast to its parent fast = (fast ? fast->get_parent_thread() : fast); - while(slow) + // The slow pointer must be valid and not have a tid of -1. + while(slow && slow->m_tid != -1) { if(!visitor(slow)) { @@ -919,15 +920,20 @@ void sinsp_threadinfo::traverse_parent_state(visitor_func_t &visitor) for (uint32_t i = 0; i < 2; i++) { fast = (fast ? fast->get_parent_thread() : fast); - // If not at the end but fast == slow, there's a loop - // in the thread state. - if(slow && (slow == fast)) + // If not at the end but fast == slow or if + // slow points to itself, there's a loop in + // the thread state. + if(slow && (slow == fast || + slow->m_tid == slow->m_ptid)) { // Note we only log a loop once for a given main thread, to avoid flooding logs. if(!m_parent_loop_detected) { g_logger.log(string("Loop in parent thread state detected for pid ") + - std::to_string(m_pid), sinsp_logger::SEV_WARNING); + std::to_string(m_pid) + + ". stopped at tid= " + std::to_string(slow->m_tid) + + " ptid=" + std::to_string(slow->m_ptid), + sinsp_logger::SEV_WARNING); m_parent_loop_detected = true; } return;