From d4ca93305f90e8b9d32824f8f5711839e015d976 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Wed, 25 Sep 2024 09:21:59 +0200 Subject: [PATCH 01/20] fix(test/libsinsp_e2e): remove multithreaded usage of sinsp inspector in e2e tests. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/capture_to_file_test.cpp | 2 +- test/libsinsp_e2e/container/container.cpp | 132 ++++--- test/libsinsp_e2e/event_capture.cpp | 321 ++++++++---------- test/libsinsp_e2e/event_capture.h | 189 ++++------- test/libsinsp_e2e/forking.cpp | 113 +++--- test/libsinsp_e2e/fs.cpp | 44 ++- test/libsinsp_e2e/paths.cpp | 13 +- test/libsinsp_e2e/process.cpp | 22 +- test/libsinsp_e2e/suppress_events.cpp | 36 +- test/libsinsp_e2e/sys_call_test.cpp | 165 ++++----- test/libsinsp_e2e/sys_call_test.h | 10 +- test/libsinsp_e2e/tcp_client_server.cpp | 14 +- .../tcp_client_server_ipv4_mapped.cpp | 5 +- test/libsinsp_e2e/test_helper.cpp | 2 +- test/libsinsp_e2e/udp_client_server.cpp | 16 +- test/libsinsp_e2e/unix_client_server.cpp | 2 +- 16 files changed, 468 insertions(+), 618 deletions(-) diff --git a/test/libsinsp_e2e/capture_to_file_test.cpp b/test/libsinsp_e2e/capture_to_file_test.cpp index 0627501451..4e73fb00fa 100644 --- a/test/libsinsp_e2e/capture_to_file_test.cpp +++ b/test/libsinsp_e2e/capture_to_file_test.cpp @@ -32,7 +32,7 @@ TEST_F(sys_call_test, can_consume_a_capture_file) { evt->get_direction() == SCAP_ED_OUT; }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { struct stat sb; for(int i = 0; i < 100; i++) { stat("/tmp", &sb); diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 195f2b6a37..6ed4a886b7 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -27,20 +27,21 @@ limitations under the License. using namespace std; TEST_F(sys_call_test, container_cgroups) { - int ctid; + int ctid = -1; bool done = false; // // FILTER // - event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ctid; }; + event_filter_t filter = [&](sinsp_evt* evt) { + return evt->get_type() == PPME_SYSCALL_CLONE_20_X && evt->get_tid() == ctid; + }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { ctid = fork(); - if(ctid >= 0) { if(ctid == 0) { sleep(1); @@ -55,58 +56,55 @@ TEST_F(sys_call_test, container_cgroups) { }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { - if(param.m_evt->get_type() == PPME_SYSCALL_CLONE_20_X) { - sinsp_threadinfo sinsp_tinfo(nullptr); - char buf[100]; + sinsp_threadinfo sinsp_tinfo(nullptr); + char buf[100]; - sinsp_threadinfo* tinfo = param.m_evt->get_thread_info(); - ASSERT_TRUE(tinfo != NULL); - const auto& cgroups = tinfo->cgroups(); - ASSERT_TRUE(cgroups.size() > 0); + sinsp_threadinfo* tinfo = param.m_evt->get_thread_info(); + ASSERT_TRUE(tinfo != nullptr); + const auto& cgroups = tinfo->cgroups(); + ASSERT_TRUE(!cgroups.empty()); - snprintf(buf, sizeof(buf), "/proc/%d/", ctid); + snprintf(buf, sizeof(buf), "/proc/%d/", ctid); - sinsp_tinfo.m_tid = ctid; - sinsp_cgroup::instance().lookup_cgroups(sinsp_tinfo); + sinsp_tinfo.m_tid = ctid; + sinsp_cgroup::instance().lookup_cgroups(sinsp_tinfo); - const auto& sinsp_cgroups = sinsp_tinfo.cgroups(); - ASSERT_TRUE(sinsp_cgroups.size() > 0); + const auto& sinsp_cgroups = sinsp_tinfo.cgroups(); + ASSERT_TRUE(!sinsp_cgroups.empty()); - map cgroups_kernel; - for(uint32_t j = 0; j < cgroups.size(); ++j) { - cgroups_kernel.insert(pair(cgroups[j].first, cgroups[j].second)); - } + map cgroups_kernel; + for(const auto& cgroup : cgroups) { + cgroups_kernel.insert(pair(cgroup.first, cgroup.second)); + } - map cgroups_proc; - for(uint32_t j = 0; j < sinsp_cgroups.size(); ++j) { - cgroups_proc.insert( - pair(sinsp_cgroups[j].first, sinsp_cgroups[j].second)); - } + map cgroups_proc; + for(const auto& sinsp_cgroup : sinsp_cgroups) { + cgroups_proc.insert(pair(sinsp_cgroup.first, sinsp_cgroup.second)); + } - ASSERT_TRUE(cgroups_kernel.size() > 0); - ASSERT_TRUE(cgroups_proc.size() > 0); + ASSERT_TRUE(!cgroups_kernel.empty()); + ASSERT_TRUE(!cgroups_proc.empty()); - for(const auto& [subsys, path] : cgroups_proc) { - printf(" proc cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); - } + for(const auto& [subsys, path] : cgroups_proc) { + printf(" proc cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); + } - for(const auto& [subsys, path] : cgroups_kernel) { - printf(" kernel cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); - } + for(const auto& [subsys, path] : cgroups_kernel) { + printf(" kernel cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); + } - for(auto& [proc_subsys, proc_path] : cgroups_proc) { - auto it_kernel = cgroups_kernel.find(proc_subsys); - if(it_kernel != cgroups_kernel.end()) { - EXPECT_EQ(it_kernel->first, proc_subsys); - EXPECT_EQ(it_kernel->second, proc_path); - } + for(auto& [proc_subsys, proc_path] : cgroups_proc) { + auto it_kernel = cgroups_kernel.find(proc_subsys); + if(it_kernel != cgroups_kernel.end()) { + ASSERT_EQ(it_kernel->first, proc_subsys); + ASSERT_EQ(it_kernel->second, proc_path); } - - done = true; } + + done = true; }; ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); @@ -136,7 +134,7 @@ TEST_F(sys_call_test, container_clone_nspid) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stack_top; /* End of stack buffer area */ @@ -206,9 +204,7 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { - waitpid(ctid, NULL, 0); - }; + run_callback_t test = [&]() { waitpid(ctid, NULL, 0); }; // // OUTPUT VALDATION @@ -238,7 +234,7 @@ static void run_container_docker_test(bool fork_after_container_start) { evt->get_type() == PPME_CONTAINER_JSON_2_E); }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { ASSERT_TRUE(system("docker kill libsinsp_docker > /dev/null 2>&1 || true") == 0); ASSERT_TRUE(system("docker rm -v libsinsp_docker > /dev/null 2>&1 || true") == 0); @@ -346,7 +342,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { return false; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { ASSERT_TRUE(system("docker kill libsinsp_docker > /dev/null 2>&1 || true") == 0); ASSERT_TRUE(system("docker rm -v libsinsp_docker > /dev/null 2>&1 || true") == 0); @@ -408,7 +404,7 @@ TEST_F(sys_call_test, container_libvirt) { return false; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { FILE* f = fopen("/tmp/conf.xml", "w"); ASSERT_TRUE(f != NULL); fprintf(f, @@ -597,24 +593,21 @@ static void healthcheck_helper( ASSERT_TRUE(dhelper.build_image() == 0); - before_open_t setup = [&](sinsp* inspector) {}; + before_open_t setup = [&](sinsp* inspector) { + // Setting dropping mode preserves the execs but + // reduces the chances that we'll drop events during + // the docker fetch. + inspector->start_dropping_mode(1); + }; event_filter_t filter = [&](sinsp_evt* evt) { sinsp_threadinfo* tinfo = evt->get_thread_info(); - return (strcmp(evt->get_name(), "execve") == 0 && evt->get_direction() == SCAP_ED_OUT && - tinfo->m_container_id != ""); + return (tinfo != nullptr && strcmp(evt->get_name(), "execve") == 0 && + evt->get_direction() == SCAP_ED_OUT && !tinfo->m_container_id.empty()); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - // Setting dropping mode preserves the execs but - // reduces the chances that we'll drop events during - // the docker fetch. - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->start_dropping_mode(1); - } - + run_callback_t test = [&]() { int rc = dhelper.run_container("cont_health_ut", "/bin/sh -c '/bin/sleep 10'"); ASSERT_TRUE(exited_early || (rc == 0)); @@ -657,7 +650,7 @@ static void healthcheck_tracefile_helper( dockerfile + " . > /dev/null 2>&1"); ASSERT_TRUE(system(build_cmdline.c_str()) == 0); - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { // --network=none speeds up the container setup a bit. ASSERT_TRUE( (system("docker run --rm --network=none --name cont_health_ut cont_health_ut_img " @@ -687,7 +680,7 @@ static void healthcheck_tracefile_helper( inspector.open_savefile(dumpfile); inspector.start_capture(); - while(1) { + while(true) { sinsp_evt* ev; int32_t res = inspector.next(&ev); @@ -819,17 +812,16 @@ TEST_F(sys_call_test, docker_container_large_json) { ASSERT_TRUE(dhelper.build_image() == 0); + before_open_t before = [&](sinsp* inspector) { + inspector->set_container_labels_max_len(60000); + }; + event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() == PPME_CONTAINER_JSON_E || evt->get_type() == PPME_CONTAINER_JSON_2_E; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - // set container label max to huge value - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->set_container_labels_max_len(60000); - } + run_callback_t test = [&]() { int rc = dhelper.run_container("large_container_ut", "/bin/sh -c '/bin/sleep 3'"); ASSERT_TRUE(rc == 0); @@ -873,6 +865,6 @@ TEST_F(sys_call_test, docker_container_large_json) { param.m_inspector->set_container_labels_max_len(100); }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); ASSERT_TRUE(saw_container_evt); } diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 5face207e8..9ffdb38ec5 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -24,208 +24,164 @@ limitations under the License. #include #include #include - -std::string event_capture::m_engine_string = KMOD_ENGINE; -std::string event_capture::m_engine_path = ""; -unsigned long event_capture::m_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; -bool event_capture::inspector_ok = false; - -concurrent_object_handle event_capture::get_inspector_handle() { - return {get_inspector(), m_inspector_mutex}; +#include + +std::string event_capture::s_engine_string = KMOD_ENGINE; +std::string event_capture::s_engine_path; +unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; +int event_capture::s_eventfd = -1; + +event_capture::event_capture(sinsp_mode_t mode, + captured_event_callback_t captured_event_callback, + before_open_t before_open, + before_close_t before_close, + event_filter_t filter, + uint32_t max_thread_table_size, + uint64_t thread_timeout_ns, + uint64_t inactive_thread_scan_time_ns, + uint64_t max_timeouts) { + m_mode = mode; + + m_captured_event_callback = std::move(captured_event_callback); + m_before_open = std::move(before_open); + m_before_close = std::move(before_close); + m_filter = std::move(filter); + m_max_timeouts = max_timeouts; + + s_eventfd = eventfd(0, EFD_NONBLOCK); + m_inspector = std::make_unique(); + m_inspector->m_thread_manager->set_max_thread_table_size(max_thread_table_size); + m_inspector->m_thread_timeout_ns = thread_timeout_ns; + m_inspector->set_auto_threads_purging_interval_s(inactive_thread_scan_time_ns); + m_inspector->set_auto_threads_purging(false); + m_inspector->set_get_procs_cpu_from_driver(true); + m_inspector->set_debug_mode(true); + m_inspector->set_hostname_and_port_resolution_mode(false); + + m_param.m_inspector = m_inspector.get(); } -void event_capture::init_inspector() { - get_inspector()->m_thread_manager->set_max_thread_table_size(m_max_thread_table_size); - get_inspector()->m_thread_timeout_ns = m_thread_timeout_ns; - get_inspector()->set_auto_threads_purging_interval_s(m_inactive_thread_scan_time_ns); - get_inspector()->set_auto_threads_purging(false); - - get_inspector()->set_get_procs_cpu_from_driver(true); +event_capture::~event_capture() { + close(s_eventfd); + s_eventfd = -1; +} - ASSERT_FALSE(get_inspector()->is_capture()); - ASSERT_FALSE(get_inspector()->is_live()); - ASSERT_FALSE(get_inspector()->is_nodriver()); +void event_capture::start(bool dump) { + open_engine(event_capture::get_engine(), {}); - try { - if(m_mode == SINSP_MODE_NODRIVER) { - get_inspector()->open_nodriver(); - } else { - open_engine(event_capture::get_engine(), {}); - } - } catch(sinsp_exception& e) { - m_start_failed = true; - m_start_failure_message = - "couldn't open inspector (maybe driver hasn't been loaded yet?) err=" + - get_inspector()->getlasterr() + " exception=" + e.what(); - { - m_capture_started = true; - m_condition_started.notify_one(); - } - return; + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + if(dump) { + auto dump_filename = std::string(LIBSINSP_TEST_CAPTURES_PATH) + + test_info->test_case_name() + "_" + test_info->name() + ".scap"; + m_dumper = std::make_unique(m_inspector.get(), + dump_filename.c_str(), + 0, + 0, + 0, + 0, + true); } - get_inspector()->set_debug_mode(true); - get_inspector()->set_hostname_and_port_resolution_mode(false); + m_before_open(m_inspector.get()); + m_inspector->start_capture(); } -void event_capture::capture() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - std::unique_ptr dumper; - { - std::scoped_lock init_lock(m_inspector_mutex, m_object_state_mutex); - - if(!inspector_ok) { - init_inspector(); - if(!m_start_failed) { - inspector_ok = true; - } else { - std::cerr << m_start_failure_message << std::endl; - return; - } - } +void event_capture::stop() { + // Begin teardown synchronized section + m_before_close(m_inspector.get()); - m_param.m_inspector = get_inspector(); - - m_before_open(get_inspector()); - - get_inspector()->start_capture(); - if(m_mode != SINSP_MODE_NODRIVER) { - m_dump_filename = std::string(LIBSINSP_TEST_CAPTURES_PATH) + - test_info->test_case_name() + "_" + test_info->name() + ".scap"; - dumper = std::make_unique(get_inspector(), - m_dump_filename.c_str(), - 0, - 0, - 0, - 0, - true); - } - } // End init synchronized section + m_inspector->stop_capture(); + if(m_dumper != nullptr) { + m_dumper->close(); + } +} - bool signaled_start = false; +void event_capture::capture() { sinsp_evt* event; bool result = true; int32_t next_result = SCAP_SUCCESS; + + uint32_t n_timeouts = 0; while(result && !::testing::Test::HasFatalFailure()) { - { - std::lock_guard lock(m_object_state_mutex); - if(m_capture_stopped) { - break; - } - } - { - std::scoped_lock inspector_next_lock(m_inspector_mutex); - next_result = get_inspector()->next(&event); + if(handle_request()) { + continue; } - if(SCAP_SUCCESS == next_result) { - result = handle_event(event); - if(m_mode != SINSP_MODE_NODRIVER && m_dump) { - dumper->dump(event); - } - } - if(!signaled_start) { - signaled_start = true; - { - std::lock_guard lock(m_object_state_mutex); - m_capture_started = true; - } - m_condition_started.notify_one(); - } - } - if(m_mode != SINSP_MODE_NODRIVER) { - uint32_t n_timeouts = 0; - while(result && !::testing::Test::HasFatalFailure()) { - { - std::scoped_lock inspector_next_lock(m_inspector_mutex); - next_result = get_inspector()->next(&event); - } - if(next_result == SCAP_TIMEOUT) { - n_timeouts++; - - if(n_timeouts < m_max_timeouts) { - continue; - } else { - break; - } - } + next_result = m_inspector->next(&event); + if(next_result == SCAP_TIMEOUT) { + n_timeouts++; - if(next_result == SCAP_FILTERED_EVENT) { + if(n_timeouts < m_max_timeouts) { continue; - } - if(next_result != SCAP_SUCCESS) { + } else { break; } - if(m_dump) { - dumper->dump(event); - } - result = handle_event(event); - } - { - std::scoped_lock inspector_next_lock(m_inspector_mutex); - while(SCAP_SUCCESS == get_inspector()->next(&event)) { - // just consume the remaining events - } } - } - { // Begin teardown synchronized section - std::scoped_lock teardown_lock(m_inspector_mutex, m_object_state_mutex); - m_before_close(get_inspector()); - - get_inspector()->stop_capture(); - if(m_mode != SINSP_MODE_NODRIVER) { - dumper->close(); + if(next_result == SCAP_FILTERED_EVENT) { + continue; } - - m_capture_stopped = true; - } // End teardown synchronized section - - m_condition_stopped.notify_one(); -} - -void event_capture::stop_capture() { - { - std::scoped_lock init_lock(m_inspector_mutex, m_object_state_mutex); - get_inspector()->stop_capture(); - m_capture_stopped = true; - m_condition_stopped.notify_one(); + if(next_result != SCAP_SUCCESS) { + break; + } + if(m_dumper != nullptr) { + m_dumper->dump(event); + } + result = handle_event(event); } } -void event_capture::wait_for_capture_start() { - std::unique_lock lock(m_object_state_mutex); - m_condition_started.wait(lock, [this]() { return m_capture_started; }); +// Returns true if the current iteration can be skipped +bool event_capture::handle_request() { + eventfd_t req; + int ret = eventfd_read(s_eventfd, &req); + if(ret == 0) { + // manage request + switch(req) { + case E2E_REQ_STOP_CAPTURE: { + m_inspector->stop_capture(); + int oldfl; + oldfl = fcntl(s_eventfd, F_GETFL); + // Drop the nonblock mode on the FD to avoid busy loop; + // instead, main loop will block until start_capture is requested + fcntl(s_eventfd, F_SETFL, oldfl & ~O_NONBLOCK); + return true; + } + case E2E_REQ_START_CAPTURE: { + m_inspector->start_capture(); + int oldfl; + oldfl = fcntl(s_eventfd, F_GETFL); + // Reset the O_NONBLOCK flag to avoid the blocking read from the eventfd. + fcntl(s_eventfd, F_SETFL, oldfl | O_NONBLOCK); + break; + } + case E2E_REQ_SUPPRESS_SH: + m_inspector->suppress_events_comm("test_helper.sh"); + break; + case E2E_REQ_SUPPRESS: + m_inspector->suppress_events_comm("test_helper"); + break; + default: + break; + } + } + return false; } -void event_capture::wait_for_capture_stop() { - std::unique_lock lock(m_object_state_mutex); - m_condition_stopped.wait(lock, [this]() { return m_capture_stopped; }); -} +bool event_capture::handle_event(sinsp_evt* event) { + bool res = true; -void event_capture::re_read_dump_file() { - try { - sinsp inspector; - sinsp_evt* event; - - inspector.open_savefile(m_dump_filename); - uint32_t res; - do { - res = inspector.next(&event); - } while(res == SCAP_SUCCESS); - ASSERT_EQ((int)SCAP_EOF, (int)res); - } catch(sinsp_exception& e) { - FAIL() << "caught exception " << e.what(); + // Signal to exit! + if(event->get_type() == PPME_SYSCALL_CLOSE_E && + event->get_param(0)->as() == FD_SIGNAL_STOP) { + return false; } -} -bool event_capture::handle_event(sinsp_evt* event) { - std::unique_lock object_state_lock(m_object_state_mutex); if(::testing::Test::HasNonfatalFailure()) { return true; } - bool res = true; + if(m_filter(event)) { try { m_param.m_evt = event; @@ -234,11 +190,8 @@ bool event_capture::handle_event(sinsp_evt* event) { res = false; } } - if(!m_capture_continue()) { - return false; - } if(!res || ::testing::Test::HasNonfatalFailure()) { - std::cerr << "failed on event " << event->get_num() << std::endl; + std::cerr << "failed on event " << event->get_num() << '\n'; } return res; } @@ -249,7 +202,7 @@ void event_capture::open_engine(const std::string& engine_string, } #ifdef HAS_ENGINE_KMOD else if(!engine_string.compare(KMOD_ENGINE)) { - get_inspector()->open_kmod(m_buffer_dim); + m_inspector->open_kmod(s_buffer_dim); } #endif #ifdef HAS_ENGINE_BPF @@ -259,33 +212,39 @@ void event_capture::open_engine(const std::string& engine_string, << std::endl; exit(EXIT_FAILURE); } - get_inspector()->open_bpf(event_capture::get_engine_path().c_str(), m_buffer_dim); + m_inspector->open_bpf(event_capture::get_engine_path(), s_buffer_dim); } #endif #ifdef HAS_ENGINE_MODERN_BPF else if(!engine_string.compare(MODERN_BPF_ENGINE)) { - get_inspector()->open_modern_bpf(m_buffer_dim); + m_inspector->open_modern_bpf(s_buffer_dim); } #endif else { - std::cerr << "Unknown engine" << std::endl; + std::cerr << "Unknown engine" << '\n'; exit(EXIT_FAILURE); } } void event_capture::set_engine(const std::string& engine_string, const std::string& engine_path) { - m_engine_string = engine_string; - m_engine_path = engine_path; + s_engine_string = engine_string; + s_engine_path = engine_path; } void event_capture::set_buffer_dim(const unsigned long& dim) { - m_buffer_dim = dim; + s_buffer_dim = dim; } const std::string& event_capture::get_engine() { - return m_engine_string; + return s_engine_string; } const std::string& event_capture::get_engine_path() { - return m_engine_path; + return s_engine_path; +} + +void event_capture::do_request(e2e_req_t req) { + eventfd_write(s_eventfd, req); + // Wait for the request to be caught by the main thread + usleep(50); } diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index cac9bbe2ed..75910b29b8 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -32,63 +32,20 @@ limitations under the License. #include #include #include +#include -class concurrent_object_handle_state_error : public std::logic_error { - using std::logic_error::logic_error; -}; - -class event_capture; +// Just a stupid fake FD value to signal to stop capturing events from driver and exit. +// Note: we don't use it through eventfd because we want to make sure +// that we received all events from the driver, until this very last close(FD_SIGNAL_STOP); +#define FD_SIGNAL_STOP 555 -/** - * The concurrent_object_handle class encapsulates the task of accessing - * event_capture::m_inspector in a thread-safe way, especially in the - * run_callback_t functions passed to event_capture::run(). - */ -template -class concurrent_object_handle { -public: - friend event_capture; - - /** - * Creates a new, unlocked handle with other's wrapped pointer and underlying mutex. - * @param other - */ - concurrent_object_handle(const concurrent_object_handle& other) noexcept: - m_object_ptr(other.m_object_ptr), - m_object_lock(*other.m_object_lock.mutex(), std::defer_lock) {} - - void lock() { m_object_lock.lock(); } - - T* operator->() { - if(!m_object_lock.owns_lock()) { - throw concurrent_object_handle_state_error( - "Attempt to access wrapped object without obtaining a lock."); - } - return m_object_ptr; - } - - inline T* safe_ptr() { return operator->(); } - - T& operator*() { - if(!m_object_lock.owns_lock()) { - throw concurrent_object_handle_state_error( - "Attempt to access wrapped object without obtaining a lock."); - } - return *m_object_ptr; - } - - T* unsafe_ptr() { return m_object_ptr; } - - void unlock() { m_object_lock.unlock(); } - -private: - concurrent_object_handle(sinsp* object_ptr, std::mutex& object_mutex): - m_object_ptr(object_ptr), - m_object_lock(object_mutex, std::defer_lock) {} - - T* m_object_ptr; - std::unique_lock m_object_lock; -}; +// eventfd inter-thread requests +typedef enum : std::uint8_t { + E2E_REQ_STOP_CAPTURE = 1, + E2E_REQ_START_CAPTURE = 2, + E2E_REQ_SUPPRESS_SH = 3, + E2E_REQ_SUPPRESS = 4, +} e2e_req_t; class callback_param { public: @@ -101,115 +58,89 @@ typedef std::function before_close_t; typedef std::function event_filter_t; typedef std::function captured_event_callback_t; -// Returns true/false to indicate whether the capture should continue -// or stop -typedef std::function capture_continue_t; - -typedef std::function inspector)> run_callback_t; +typedef std::function run_callback_t; class event_capture { public: - void init_inspector(); + event_capture(sinsp_mode_t mode, + captured_event_callback_t captured_event_callback, + before_open_t before_open, + before_close_t before_close, + event_filter_t filter, + uint32_t max_thread_table_size, + uint64_t thread_timeout_ns, + uint64_t inactive_thread_scan_time_ns, + uint64_t max_timeouts); + ~event_capture(); + + void start(bool dump); + void stop(); void capture(); - void stop_capture(); - void wait_for_capture_start(); - void wait_for_capture_stop(); static void do_nothing(sinsp* inspector) {} - static bool always_continue() { return true; } - - sinsp* get_inspector() { - static sinsp inspector = sinsp(); - return &inspector; - } - static void run(run_callback_t run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, before_open_t before_open = event_capture::do_nothing, before_close_t before_close = event_capture::do_nothing, - capture_continue_t capture_continue = event_capture::always_continue, uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, sinsp_mode_t mode = SINSP_MODE_LIVE, uint64_t max_timeouts = 3, bool dump = true) { - event_capture capturing; - { // Synchronized section - std::unique_lock object_state_lock(capturing.m_object_state_mutex); - capturing.m_mode = mode; - capturing.m_captured_event_callback = captured_event_callback; - capturing.m_before_open = before_open; - capturing.m_before_close = before_close; - capturing.m_capture_continue = capture_continue; - capturing.m_filter = filter; - capturing.m_max_thread_table_size = max_thread_table_size; - capturing.m_thread_timeout_ns = thread_timeout_ns; - capturing.m_inactive_thread_scan_time_ns = inactive_thread_scan_time_ns; - capturing.m_max_timeouts = max_timeouts; - capturing.m_dump = dump; - } - - std::thread thread([&capturing]() { capturing.capture(); }); - - capturing.wait_for_capture_start(); - - if(!capturing.m_start_failed.load()) { - run_function(capturing.get_inspector_handle()); - capturing.stop_capture(); - capturing.wait_for_capture_stop(); - } else { - std::unique_lock error_lookup_lock(capturing.m_object_state_mutex); - GTEST_MESSAGE_(capturing.m_start_failure_message.c_str(), - ::testing::TestPartResult::kFatalFailure); - } - + event_capture capturing(mode, + std::move(captured_event_callback), + std::move(before_open), + std::move(before_close), + std::move(filter), + max_thread_table_size, + thread_timeout_ns, + inactive_thread_scan_time_ns, + max_timeouts); + + capturing.start(dump); + + std::thread thread([&run_function]() { + usleep(50); + run_function(); + // signal main thread to end the capture + close(FD_SIGNAL_STOP); + }); + + capturing.capture(); thread.join(); + + capturing.stop(); } + static void do_request(e2e_req_t req); + static void set_engine(const std::string& engine_string, const std::string& engine_path); static const std::string& get_engine(); static void set_buffer_dim(const unsigned long& dim); static const std::string& get_engine_path(); - static std::string m_engine_string; - static std::string m_engine_path; - static unsigned long m_buffer_dim; + static std::string s_engine_string; + static std::string s_engine_path; + static unsigned long s_buffer_dim; private: - event_capture(): m_capture_started(false), m_capture_stopped(false), m_start_failed(false) {} - - concurrent_object_handle get_inspector_handle(); - - void re_read_dump_file(); - + bool handle_request(); bool handle_event(sinsp_evt* event); void open_engine(const std::string& engine_string, libsinsp::events::set events_sc_codes); - std::mutex m_inspector_mutex; // Always lock first - std::mutex m_object_state_mutex; // Always lock second - std::condition_variable m_condition_started; - std::condition_variable m_condition_stopped; - bool m_capture_started; - bool m_capture_stopped; - std::atomic m_start_failed; - + std::unique_ptr m_inspector; + std::unique_ptr m_dumper; event_filter_t m_filter; captured_event_callback_t m_captured_event_callback; before_open_t m_before_open; before_close_t m_before_close; - capture_continue_t m_capture_continue; - uint32_t m_max_thread_table_size; - uint64_t m_thread_timeout_ns; - uint64_t m_inactive_thread_scan_time_ns; - std::string m_start_failure_message; - std::string m_dump_filename; - callback_param m_param; - static bool inspector_ok; + callback_param m_param{}; sinsp_mode_t m_mode; - uint64_t m_max_timeouts; - bool m_dump; + uint64_t m_max_timeouts{}; + + static int s_eventfd; }; diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 98a01a8154..1da5674779 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -57,7 +57,7 @@ TEST_F(sys_call_test, forking) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { pid_t childtid; int status; childtid = fork(); @@ -107,20 +107,19 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { return evt->get_tid() == ptid || evt->get_tid() == ctid; }; + before_open_t before = [&](sinsp* inspector) { + // + // Stop the capture just before the fork so we lose the event. + // + inspector->stop_capture(); + }; + // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int status; - // - // Stop the capture just before the fork so we lose the event. - // - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->stop_capture(); - } - ctid = fork(); int fd = creat(FILENAME, S_IRWXU); @@ -138,7 +137,7 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { // It's a simple way to make sure the capture is started // after the child's clone returned. // - inspector_handle.unsafe_ptr()->start_capture(); + event_capture::do_request(E2E_REQ_START_CAPTURE); // // Wait for 5 seconds to make sure the process will still @@ -197,26 +196,32 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); EXPECT_TRUE(child_exists); EXPECT_TRUE(parent_exists); } TEST_F(sys_call_test, forking_process_expired) { - int ptid; // parent tid - int ctid; // child tid + std::atomic ptid = -1; // parent tid + std::atomic ctid = -1; // child tid int status; // // FILTER // - event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ptid; }; + event_filter_t filter = [&](sinsp_evt* evt) { + if(evt->get_type() == PPME_SYSCALL_NANOSLEEP_E || + evt->get_type() == PPME_SYSCALL_NANOSLEEP_X) { + return evt->get_tid() == ptid.load(); + } + return false; + }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { ctid = fork(); if(ctid >= 0) // fork succeeded @@ -227,17 +232,16 @@ TEST_F(sys_call_test, forking_process_expired) { FAIL(); } else // fork() returns new pid to the parent process { - ptid = getpid(); + ptid = gettid(); // // Wait 10 seconds. During this time, the process should NOT be removed // - struct timespec req, rem; - req.tv_sec = 10; + struct timespec req = {0}; + req.tv_sec = 1; req.tv_nsec = 0; - syscall(__NR_nanosleep, &req, &rem); - + syscall(__NR_nanosleep, &req, nullptr); kill(ctid, SIGUSR1); wait(&status); } @@ -253,24 +257,23 @@ TEST_F(sys_call_test, forking_process_expired) { // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; - - if(e->get_tid() == ptid) { - if(e->get_type() == PPME_SYSCALL_NANOSLEEP_E && !sleep_caught) { + if(!sleep_caught) { + if(e->get_type() == PPME_SYSCALL_NANOSLEEP_E) { // // The child should exist // - sinsp_threadinfo* ti = param.m_inspector->get_thread_ref(ctid, false, true).get(); + sinsp_threadinfo* ti = + param.m_inspector->get_thread_ref(ctid.load(), false, true).get(); EXPECT_NE((sinsp_threadinfo*)NULL, ti); - } else if(e->get_type() == PPME_SYSCALL_NANOSLEEP_X && !sleep_caught) { + } else if(e->get_type() == PPME_SYSCALL_NANOSLEEP_X) { // // The child should exist // - sinsp_threadinfo* ti = param.m_inspector->get_thread_ref(ctid, false, true).get(); + sinsp_threadinfo* ti = + param.m_inspector->get_thread_ref(ctid.load(), false, true).get(); EXPECT_NE((sinsp_threadinfo*)NULL, ti); sleep_caught = true; } - } else { - FAIL(); } }; @@ -280,7 +283,6 @@ TEST_F(sys_call_test, forking_process_expired) { filter, event_capture::do_nothing, event_capture::do_nothing, - event_capture::always_continue, 131072, 5 * ONE_SECOND_IN_NS, ONE_SECOND_IN_NS); @@ -292,7 +294,7 @@ TEST_F(sys_call_test, forking_process_expired) { /////////////////////////////////////////////////////////////////////////////// // CLONE VARIANTS /////////////////////////////////////////////////////////////////////////////// -int ctid; // child tid +std::atomic ctid = -1; // child tid typedef struct { int fd; @@ -328,7 +330,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { int callnum = 0; char bcwd[1024]; int prfd; - int ptid; // parent tid + std::atomic ptid; // parent tid pid_t clone_tid; int child_tid; int parent_res; @@ -340,13 +342,13 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { // FILTER // event_filter_t filter = [&](sinsp_evt* evt) { - return evt->get_tid() == ptid || evt->get_tid() == child_tid; + return evt->get_tid() == ptid.load() || evt->get_tid() == child_tid; }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ @@ -467,7 +469,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { int callnum = 0; char bcwd[1024]; int prfd; - int ptid; // parent tid + std::atomic ptid = -1; // parent tid int flags = CLONE_FS | CLONE_VM; int drflags = PPM_CL_CLONE_FS | PPM_CL_CLONE_VM; @@ -475,13 +477,13 @@ TEST_F(sys_call_test, forking_clone_nofs) { // FILTER // event_filter_t filter = [&](sinsp_evt* evt) { - return evt->get_tid() == ptid || evt->get_tid() == ctid; + return evt->get_tid() == ptid.load() || evt->get_tid() == ctid; }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ @@ -489,7 +491,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { int status; pid_t pid; - ptid = getpid(); + ptid = gettid(); /* Set up an argument structure to be passed to cloned child, and set some process attributes that will be modified by child */ @@ -605,7 +607,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { int callnum = 0; char oriwd[1024]; char bcwd[256]; - int ptid; // parent tid + std::atomic ptid = -1; // parent tid int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD; int drflags = PPM_CL_CLONE_VM | PPM_CL_CLONE_FS | PPM_CL_CLONE_FILES | PPM_CL_CLONE_SIGHAND | PPM_CL_CLONE_THREAD; @@ -613,18 +615,17 @@ TEST_F(sys_call_test, forking_clone_cwd) { // // FILTER // - event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ptid; }; + event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ptid.load(); }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ - clone_params cp; /* Passed to child function */ - ptid = getpid(); + ptid = gettid(); ASSERT_TRUE(getcwd(oriwd, 1024) != NULL); @@ -637,17 +638,16 @@ TEST_F(sys_call_test, forking_clone_cwd) { /* Create child; child commences execution in childFunc() */ - if(clone(clone_callback_2, stackTop, flags, &cp) == -1) { + if(clone(clone_callback_2, stackTop, flags, nullptr) == -1) { FAIL(); } - sleep(1); + usleep(500); std::string tmps = getcwd(bcwd, 256); ASSERT_TRUE(chdir(oriwd) == 0); - sleep(1); free(stack); }; @@ -708,7 +708,7 @@ TEST_F(sys_call_test, forking_main_thread_exit) { } }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { int status; // ptid = getpid(); @@ -776,17 +776,11 @@ TEST_F(sys_call_test, forking_main_thread_exit) { // Create the initial stale process. It chdir()s to "/dev", stops the // inspector, and returns. static int stop_sinsp_and_exit(void* arg) { - // Get our own, unlocked concurrent inspector handle - concurrent_object_handle inspector_handle = *(concurrent_object_handle*)arg; - if(chdir("/dev") != 0) { return 1; } - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->stop_capture(); - } + event_capture::do_request(E2E_REQ_STOP_CAPTURE); // Wait 5 seconds. This ensures that the state for this // process will be considered stale when the second process @@ -907,7 +901,7 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { return (rp != 0 && tinfo && tinfo->m_tid == rp); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { pid_t launcher_pid; char* launcher_stack = NULL; @@ -924,15 +918,14 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // Start a thread that runs and stops the inspector_handle right // before exiting. This gives us a pid we can use for the // second thread. - recycle_pid.store(clone_helper(stop_sinsp_and_exit, &inspector_handle)); + recycle_pid.store(clone_helper(stop_sinsp_and_exit, nullptr)); ASSERT_GE(recycle_pid.load(), 0); + usleep(500); + // The first thread has started, turned off the capturing, and // exited, so start capturing again. - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->start_capture(); - } + event_capture::do_request(E2E_REQ_START_CAPTURE); // Arrange that the next thread/process created has // pid ctx.m_desired pid by writing to diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index 647f548034..b51ec90f39 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -69,7 +69,7 @@ TEST_F(sys_call_test, fs_creat_ulink) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { int fd = creat(FILENAME, 0644); if(fd < 0) { @@ -158,7 +158,7 @@ TEST_F(sys_call_test, fs_mkdir_rmdir) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { mkdir(UNEXISTENT_DIRNAME, 0); if(mkdir(DIRNAME, 0) != 0) { @@ -262,7 +262,7 @@ TEST_F(sys_call_test, fs_openat) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { dirfd = open(".", O_DIRECTORY); if(dirfd <= 0) { FAIL(); @@ -341,7 +341,7 @@ TEST_F(sys_call_test, fs_pread) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { fd = creat(FILENAME, S_IRWXU); if(fd < 0) { FAIL(); @@ -467,7 +467,7 @@ TEST_F(sys_call_test, fs_readv) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { int wv_count; char msg1[10] = "aaaaa"; char msg2[10] = "bbbbb"; @@ -561,7 +561,7 @@ TEST_F(sys_call_test, fs_preadv) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { int wv_count; char msg1[10] = "aaaaa"; char msg2[10] = "bbbbb"; @@ -698,7 +698,7 @@ TEST_F(sys_call_test, fs_dup) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { fd = open(FILENAME, O_CREAT | O_WRONLY, 0); fd1 = dup(fd); fd2 = dup2(fd, 333); @@ -823,7 +823,7 @@ TEST_F(sys_call_test, fs_fcntl) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { fd = open(FILENAME, O_CREAT | O_WRONLY, 0); fd1 = fcntl(fd, F_DUPFD, 0); fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 0); @@ -897,7 +897,7 @@ TEST_F(sys_call_test, fs_sendfile) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -955,7 +955,7 @@ TEST_F(sys_call_test, fs_sendfile_nulloff) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1011,7 +1011,7 @@ TEST_F(sys_call_test, fs_sendfile_failed) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { int res = sendfile(-1, -2, NULL, 444); EXPECT_GT(0, res); }; @@ -1060,7 +1060,7 @@ TEST_F(sys_call_test, fs_sendfile_invalidoff) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1120,7 +1120,7 @@ TEST_F(sys_call_test, fs_sendfile64) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1178,7 +1178,7 @@ TEST_F(sys_call_test, large_read_write) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { fd1 = creat(FILENAME, S_IRWXU); if(fd1 < 0) { FAIL(); @@ -1245,7 +1245,6 @@ TEST_F(sys_call_test, large_read_write) { filter, setup, cleanup, - event_capture::always_continue, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, @@ -1275,7 +1274,7 @@ TEST_F(sys_call_test, large_readv_writev) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { fd = creat(FILENAME, S_IRWXU); if(fd < 0) { FAIL(); @@ -1324,7 +1323,7 @@ TEST_F(sys_call_test, large_readv_writev) { } else if(type == PPME_SYSCALL_WRITEV_X) { if(callnum == 1) { const sinsp_evt_param* p = e->get_param_by_name("data"); - if(event_capture::m_engine_string == KMOD_ENGINE) { + if(event_capture::s_engine_string == KMOD_ENGINE) { // // The driver doesn't have the correct behavior for accumulating // readv/writev, and it uses a single page as a temporary storage area @@ -1346,7 +1345,7 @@ TEST_F(sys_call_test, large_readv_writev) { } else if(type == PPME_SYSCALL_READV_X) { if(callnum == 3) { const sinsp_evt_param* p = e->get_param_by_name("data"); - if(event_capture::m_engine_string == KMOD_ENGINE) { + if(event_capture::s_engine_string == KMOD_ENGINE) { EXPECT_EQ(p->m_len, max_kmod_buf); EXPECT_EQ(0, memcmp(buf, p->m_val, max_kmod_buf)); } else { @@ -1368,7 +1367,6 @@ TEST_F(sys_call_test, large_readv_writev) { filter, setup, cleanup, - event_capture::always_continue, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, @@ -1394,7 +1392,7 @@ TEST_F(sys_call_test, large_open) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { #ifdef SYS_open int fd = syscall(SYS_open, buf.c_str(), O_RDONLY); #else @@ -1412,13 +1410,13 @@ TEST_F(sys_call_test, large_open) { } else if(name.find("open") != std::string::npos && e->get_direction() == SCAP_ED_OUT) { const sinsp_evt_param* p = e->get_param_by_name("name"); - if(event_capture::m_engine_string == KMOD_ENGINE) { + if(event_capture::s_engine_string == KMOD_ENGINE) { EXPECT_EQ(p->m_len, PPM_MAX_ARG_SIZE); EXPECT_EQ(buf.substr(0, PPM_MAX_ARG_SIZE - 1), std::string(p->m_val)); - } else if(event_capture::m_engine_string == BPF_ENGINE) { + } else if(event_capture::s_engine_string == BPF_ENGINE) { EXPECT_EQ(p->m_len, SNAPLEN_MAX); EXPECT_EQ(buf.substr(0, SNAPLEN_MAX - 1), std::string(p->m_val)); - } else if(event_capture::m_engine_string == MODERN_BPF_ENGINE) { + } else if(event_capture::s_engine_string == MODERN_BPF_ENGINE) { EXPECT_EQ(p->m_len, PATH_MAX); EXPECT_EQ(buf.substr(0, PATH_MAX - 1), std::string(p->m_val)); } diff --git a/test/libsinsp_e2e/paths.cpp b/test/libsinsp_e2e/paths.cpp index 881da21789..bdbd80583d 100644 --- a/test/libsinsp_e2e/paths.cpp +++ b/test/libsinsp_e2e/paths.cpp @@ -125,14 +125,15 @@ void testdir(string filename, string chdirtarget = "") { // // FILTER // - int tid = getpid(); + int tid = -1; event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == tid; }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - if(chdirtarget != "") { + run_callback_t test = [&]() { + tid = gettid(); + if(!chdirtarget.empty()) { char tcwd[1024]; ASSERT_TRUE(chdir(chdirtarget.c_str()) == 0); @@ -156,7 +157,7 @@ void testdir(string filename, string chdirtarget = "") { unlink(vldt.m_filename.c_str()); - if(chdirtarget != "") { + if(!chdirtarget.empty()) { ASSERT_TRUE(chdir(bcwd) == 0); } }; @@ -421,7 +422,7 @@ TEST_F(sys_call_test, dir_getcwd) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { ASSERT_TRUE(chdir(dir0) == 0); ASSERT_TRUE(getcwd(cwd0, 256) != NULL); @@ -540,7 +541,7 @@ TEST_F(sys_call_test, dir_fchdir) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int fd; fd = open(dir0, O_RDONLY); diff --git a/test/libsinsp_e2e/process.cpp b/test/libsinsp_e2e/process.cpp index ad556bd587..ec0ba53b51 100644 --- a/test/libsinsp_e2e/process.cpp +++ b/test/libsinsp_e2e/process.cpp @@ -52,8 +52,8 @@ limitations under the License. TEST_F(sys_call_test, process_signalfd_kill) { int callnum = 0; - int ptid; // parent tid - int ctid; // child tid + int ptid = -1; // parent tid + int ctid = -1; // child tid int gptid; // grandparent tid int xstatus = 33; // child exit value int ssfd; @@ -68,7 +68,7 @@ TEST_F(sys_call_test, process_signalfd_kill) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int status; int sfd; ctid = fork(); @@ -136,7 +136,7 @@ TEST_F(sys_call_test, process_signalfd_kill) { // // PARENT PROCESS // - ptid = getpid(); + ptid = gettid(); gptid = getppid(); // @@ -219,7 +219,7 @@ TEST_F(sys_call_test, DISABLED_process_usleep) { // // TEST CODE // - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { struct timespec req; req.tv_sec = 0; req.tv_nsec = 123456; @@ -271,7 +271,7 @@ TEST_F(sys_call_test, process_inotify) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int length; int wd; char buffer[EVENT_BUF_LEN]; @@ -387,7 +387,7 @@ TEST_F(sys_call_test, process_rlimit) { // // TEST CODE // - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { struct rlimit rl; sleep(1); @@ -498,7 +498,7 @@ TEST_F(sys_call_test, process_prlimit) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { struct rlimit newrl; struct rlimit oldrl; @@ -617,7 +617,7 @@ TEST_F(sys_call_test, process_scap_proc_get) { // // TEST CODE // - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { usleep(1000); int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -715,7 +715,7 @@ TEST_F(sys_call_test, procinfo_processchild_cpuload) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { for(uint32_t j = 0; j < 5; j++) { sleep(1); } @@ -786,7 +786,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { for(uint32_t j = 0; j < 5; j++) { sleep(1); } diff --git a/test/libsinsp_e2e/suppress_events.cpp b/test/libsinsp_e2e/suppress_events.cpp index 0e8c945b0c..1cae5aef2c 100644 --- a/test/libsinsp_e2e/suppress_events.cpp +++ b/test/libsinsp_e2e/suppress_events.cpp @@ -25,7 +25,6 @@ static void test_helper_quotactl(test_helper_args& hargs) { // the capture has started we let the test_helper process // perform its work. pid_t pid = getpid(); - bool test_helper_done = false; std::string bin = LIBSINSP_TEST_PATH "/test_helper"; if(hargs.spawn_with_bash) { @@ -62,11 +61,10 @@ static void test_helper_quotactl(test_helper_args& hargs) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { if(!hargs.suppress_before) { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->suppress_events_comm( - std::string((hargs.spawn_with_bash ? "test_helper.sh" : "test_helper"))); + event_capture::do_request(hargs.spawn_with_bash ? E2E_REQ_SUPPRESS_SH + : E2E_REQ_SUPPRESS); } if(!hargs.start_before) { @@ -97,8 +95,6 @@ static void test_helper_quotactl(test_helper_args& hargs) { case PPME_SYSCALL_QUOTACTL_X: if(evt->get_tid() != pid) { FAIL() << "Should not have observed any quotactl event"; - } else { - test_helper_done = true; } break; case PPME_PROCEXIT_1_E: @@ -107,8 +103,6 @@ static void test_helper_quotactl(test_helper_args& hargs) { } }; - capture_continue_t should_continue = [&]() { return (!test_helper_done); }; - before_close_t before_close = [](sinsp* inspector) { scap_stats st; @@ -127,7 +121,6 @@ static void test_helper_quotactl(test_helper_args& hargs) { filter, before_open, before_close, - should_continue, 131072, 6000, 6000, @@ -250,33 +243,28 @@ void suppress_types::run_test(std::vector supp_syscalls) { parse_syscall_names(supp_syscalls, m_suppressed_syscalls); parse_suppressed_types(supp_syscalls, &m_suppressed_evttypes); - // - // TEST CODE - // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + before_open_t before_open = [&](sinsp* inspector) { for(auto sc : m_suppressed_syscalls) { bool expect_exception = (sc >= PPM_SC_MAX); bool caught_exception = false; try { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->mark_ppm_sc_of_interest(sc, false); + inspector->mark_ppm_sc_of_interest(sc, false); } catch(sinsp_exception& e) { caught_exception = true; } ASSERT_EQ(expect_exception, caught_exception); } + }; - do_syscalls(); - + before_close_t before_close = [&](sinsp* inspector) { for(auto sc : m_suppressed_syscalls) { bool expect_exception = (sc >= PPM_SC_MAX); bool caught_exception = false; try { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->mark_ppm_sc_of_interest(sc, true); + inspector->mark_ppm_sc_of_interest(sc, true); } catch(sinsp_exception& e) { caught_exception = true; } @@ -285,6 +273,11 @@ void suppress_types::run_test(std::vector supp_syscalls) { } }; + // + // TEST CODE + // + run_callback_t test = [&]() { do_syscalls(); }; + // // OUTPUT VALDATION // @@ -296,7 +289,8 @@ void suppress_types::run_test(std::vector supp_syscalls) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, m_tid_filter); }); + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, m_tid_filter, before_open, before_close); }); EXPECT_EQ(m_expected_calls, callnum); } diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index f2361311f5..2af23ba379 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -95,7 +95,7 @@ TEST_F(sys_call_test, stat) { return evt_name.find("stat") != std::string::npos && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { struct stat sb; stat("/tmp", &sb); }; @@ -114,7 +114,7 @@ TEST_F(sys_call_test, open_close) { m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { int fd = open("/tmp", O_RDONLY); close(fd); }; @@ -143,7 +143,7 @@ TEST_F(sys_call_test, open_close_dropping) { m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { int fd = open("/tmp", O_RDONLY); close(fd); }; @@ -170,9 +170,7 @@ TEST_F(sys_call_test, fcntl_getfd) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - fcntl(0, F_GETFL); - }; + run_callback_t test = []() { fcntl(0, F_GETFL); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -189,9 +187,7 @@ TEST_F(sys_call_test, fcntl_getfd_dropping) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - fcntl(0, F_GETFL); - }; + run_callback_t test = []() { fcntl(0, F_GETFL); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -207,9 +203,7 @@ TEST_F(sys_call_test, bind_error) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - bind(0, NULL, 0); - }; + run_callback_t test = []() { bind(0, NULL, 0); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -226,9 +220,7 @@ TEST_F(sys_call_test, bind_error_dropping) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - bind(0, NULL, 0); - }; + run_callback_t test = []() { bind(0, NULL, 0); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -244,7 +236,7 @@ TEST_F(sys_call_test, close_badfd) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { close(-1); close(INT_MAX); }; @@ -271,7 +263,7 @@ TEST_F(sys_call_test, close_badfd_dropping) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { close(-1); close(INT_MAX); }; @@ -305,7 +297,7 @@ TEST_F(sys_call_test, poll_timeout) { std::string my_pipe[2]; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { subprocess handle(LIBSINSP_TEST_PATH "/test_helper", {"poll_timeout"}); std::stringstream ss; ss << handle.out(); @@ -376,7 +368,7 @@ TEST_F(sys_call_test, ioctl) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int status; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int fd; fd = open("/dev/ttyS0", O_RDONLY); @@ -413,7 +405,7 @@ TEST_F(sys_call_test, shutdown) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int sock; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { FAIL() << "socket() failed"; return; @@ -459,7 +451,7 @@ TEST_F(sys_call_test, timerfd) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int fd; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int ret; unsigned int ns; unsigned int sec; @@ -525,7 +517,7 @@ TEST_F(sys_call_test, timestamp) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { useconds_t sleep_period = 10; struct timeval tv; for(uint32_t j = 0; j < sizeof(timestampv) / sizeof(timestampv[0]); ++j) { @@ -554,7 +546,7 @@ TEST_F(sys_call_test, brk) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = []() { sbrk(1000); sbrk(100000); }; @@ -616,7 +608,7 @@ TEST_F(sys_call_test, mmap) { void* p; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { munmap((void*)0x50, 300); p = mmap(0, 0, @@ -770,7 +762,7 @@ TEST_F(sys_call_test, quotactl_ko) { evt->get_type() == PPME_SYSCALL_QUOTACTL_E; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { quotactl(QCMD(Q_QUOTAON, USRQUOTA), "/dev/xxx", 2, @@ -839,7 +831,7 @@ TEST_F(sys_call_test, quotactl_ok) { struct dqblk mydqblk; struct dqinfo mydqinfo; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { quotactl(QCMD(Q_QUOTAON, USRQUOTA), "/dev/loop0", 2, @@ -939,7 +931,7 @@ TEST_F(sys_call_test, getsetuid_and_gid) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { auto res = setuid(0); EXPECT_EQ(0, res); res = setgid(test_gid); @@ -1032,7 +1024,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) { event_filter_t filter = [&](sinsp_evt* evt) { return is_subprocess_execve->run(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { auto ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32 " LIBSINSP_TEST_RESOURCES_PATH "execve " LIBSINSP_TEST_RESOURCES_PATH "execve32"); @@ -1093,7 +1085,7 @@ TEST_F(sys_call_test32, quotactl_ko) { evt->get_type() == PPME_SYSCALL_QUOTACTL_E; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", {"quotactl_ko"}); handle.wait(); }; @@ -1140,7 +1132,7 @@ TEST_F(sys_call_test, setns_test) { return m_tid_filter(evt) && (evt->get_type() == PPME_SYSCALL_SETNS_E || evt->get_type() == PPME_SYSCALL_SETNS_X); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { fd = open("/proc/self/ns/net", O_RDONLY); ASSERT_NE(0, fd); ASSERT_EQ(0, setns(fd, CLONE_NEWNET)); @@ -1171,7 +1163,7 @@ TEST_F(sys_call_test, unshare_) { (evt->get_type() == PPME_SYSCALL_UNSHARE_E || evt->get_type() == PPME_SYSCALL_UNSHARE_X); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { auto child = fork(); if(child == 0) { unshare(CLONE_NEWUTS); @@ -1203,7 +1195,7 @@ TEST_F(sys_call_test, sendmsg_recvmsg_SCM_RIGHTS) { auto tinfo = evt->get_thread_info(true); return tinfo->get_comm() == "libsinsp_e2e_te" && evt->get_type() == PPME_SOCKET_RECVMSG_X; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int server_sd, worker_sd, pair_sd[2]; int rc = socketpair(AF_UNIX, SOCK_DGRAM, 0, pair_sd); ASSERT_GE(rc, 0); @@ -1290,7 +1282,7 @@ TEST_F(sys_call_test, ppoll_timeout) { ti->m_comm == "test_helper"; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { subprocess handle(LIBSINSP_TEST_PATH "/test_helper", {"ppoll_timeout"}); handle.wait(); }; @@ -1373,7 +1365,7 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { char command[] = "useradd -u 5454 testsetresuid && " "groupadd -g 6565 testsetresgid && " @@ -1484,7 +1476,7 @@ TEST_F(sys_call_test, failing_execve) { printf("%s %s %s %s %s\n", eargv[0], eargv[1], eargv[2], eargv[3], eargv[4]); printf("%s %s %s %s\n", eenvp[0], eenvp[1], eenvp[2], eenvp[3]); - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { int ret = execve(eargv[0], (char* const*)eargv, (char* const*)eenvp); ASSERT_TRUE(ret < 0); }; @@ -1537,7 +1529,7 @@ TEST_F(sys_call_test, large_execve) { buf.append(std::to_string(random())); } - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { ctid = fork(); if(ctid < 0) { @@ -1637,7 +1629,7 @@ TEST_F(sys_call_test32, failing_execve) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { auto ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32_fail"); ASSERT_TRUE(ret > 0); ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32 ./fail"); @@ -1732,7 +1724,7 @@ TEST_F(sys_call_test32, mmap) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", { "mmap_test", @@ -1889,7 +1881,7 @@ TEST_F(sys_call_test32, ppoll_timeout) { std::string my_pipe[2]; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", { "ppoll_timeout", @@ -1976,7 +1968,7 @@ TEST_F(sys_call_test32, fs_preadv) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { subprocess test_proc(LIBSINSP_TEST_PATH "/test_helper_32", {"preadv_pwritev"}); fd = std::stoi(test_proc.out()); int bool_n = std::stoi(test_proc.out()); @@ -2075,38 +2067,33 @@ TEST_F(sys_call_test, thread_lookup_static) { event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() != PPME_PROCEXIT_1_E && evt->get_tid() > 0; }; - run_callback_t test = [&](concurrent_object_handle inspector) { return; }; - captured_event_callback_t callback = [&](const callback_param& param) { return; }; - scap_linux_platform* platform; - - before_close_t before_close = [&](sinsp* inspector) { - platform = (scap_linux_platform*)inspector->get_scap_platform(); + run_callback_t test = [&]() { return; }; + captured_event_callback_t callback = [&](const callback_param& param) { + auto* platform = (scap_linux_platform*)param.m_inspector->get_scap_platform(); + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); + + EXPECT_EQ(1, scap_tinfo.tid); + EXPECT_EQ(1, scap_tinfo.pid); + EXPECT_EQ(1, scap_tinfo.vtid); + EXPECT_EQ(0, scap_tinfo.ptid); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 62725, &scap_tinfo, err_buf, false)); + EXPECT_EQ(62725, scap_tinfo.tid); + EXPECT_EQ(62725, scap_tinfo.pid); + EXPECT_EQ(62725, scap_tinfo.vtid); + EXPECT_EQ(1, scap_tinfo.ptid); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 62727, &scap_tinfo, err_buf, false)); + EXPECT_EQ(62727, scap_tinfo.tid); + EXPECT_EQ(62725, scap_tinfo.pid); + EXPECT_EQ(62727, scap_tinfo.vtid); + EXPECT_EQ(1, scap_tinfo.ptid); }; - ASSERT_NO_FATAL_FAILURE({ - event_capture::run(test, callback, filter, event_capture::do_nothing, before_close); - }); - - ASSERT_EQ(SCAP_SUCCESS, scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); - - EXPECT_EQ(1, scap_tinfo.tid); - EXPECT_EQ(1, scap_tinfo.pid); - EXPECT_EQ(1, scap_tinfo.vtid); - EXPECT_EQ(0, scap_tinfo.ptid); - - ASSERT_EQ(SCAP_SUCCESS, - scap_proc_read_thread(platform, proc, 62725, &scap_tinfo, err_buf, false)); - EXPECT_EQ(62725, scap_tinfo.tid); - EXPECT_EQ(62725, scap_tinfo.pid); - EXPECT_EQ(62725, scap_tinfo.vtid); - EXPECT_EQ(1, scap_tinfo.ptid); - - ASSERT_EQ(SCAP_SUCCESS, - scap_proc_read_thread(platform, proc, 62727, &scap_tinfo, err_buf, false)); - EXPECT_EQ(62727, scap_tinfo.tid); - EXPECT_EQ(62725, scap_tinfo.pid); - EXPECT_EQ(62727, scap_tinfo.vtid); - EXPECT_EQ(1, scap_tinfo.ptid); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); } TEST_F(sys_call_test, thread_lookup_live) { @@ -2119,7 +2106,7 @@ TEST_F(sys_call_test, thread_lookup_live) { event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() != PPME_PROCEXIT_1_E && evt->get_tid() > 0; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { // a very short sleep to gather some events, // we'll take much longer than this to process them all usleep(1000); @@ -2153,29 +2140,29 @@ TEST_F(sys_call_test, thread_lookup_live) { } }; - scap_linux_platform* platform; - before_close_t before_close = [&](sinsp* inspector) { // close scap to maintain the num_consumers at exit == 0 assertion // close_capture(scap, platform); - platform = (scap_linux_platform*)inspector->get_scap_platform(); + auto platform = (scap_linux_platform*)inspector->get_scap_platform(); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, getpid(), &scap_tinfo, err_buf, false)); + EXPECT_EQ(getpid(), scap_tinfo.tid); + EXPECT_EQ(getpid(), scap_tinfo.pid); + EXPECT_EQ(getpid(), scap_tinfo.vtid); + EXPECT_EQ(getppid(), scap_tinfo.ptid); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); + EXPECT_EQ(1, scap_tinfo.tid); + EXPECT_EQ(1, scap_tinfo.pid); + EXPECT_EQ(1, scap_tinfo.vtid); + EXPECT_EQ(0, scap_tinfo.ptid); }; + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, event_capture::do_nothing, before_close); }); - - ASSERT_EQ(SCAP_SUCCESS, - scap_proc_read_thread(platform, proc, getpid(), &scap_tinfo, err_buf, false)); - EXPECT_EQ(getpid(), scap_tinfo.tid); - EXPECT_EQ(getpid(), scap_tinfo.pid); - EXPECT_EQ(getpid(), scap_tinfo.vtid); - EXPECT_EQ(getppid(), scap_tinfo.ptid); - - ASSERT_EQ(SCAP_SUCCESS, scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); - EXPECT_EQ(1, scap_tinfo.tid); - EXPECT_EQ(1, scap_tinfo.pid); - EXPECT_EQ(1, scap_tinfo.vtid); - EXPECT_EQ(0, scap_tinfo.ptid); } TEST_F(sys_call_test, fd_name_max_path) { @@ -2189,9 +2176,7 @@ TEST_F(sys_call_test, fd_name_max_path) { m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - open(pathname.c_str(), O_RDONLY); - }; + run_callback_t test = [&]() { open(pathname.c_str(), O_RDONLY); }; sinsp_filter_check_list m_filterlist; diff --git a/test/libsinsp_e2e/sys_call_test.h b/test/libsinsp_e2e/sys_call_test.h index 1f1036ad68..8a03e8a91f 100644 --- a/test/libsinsp_e2e/sys_call_test.h +++ b/test/libsinsp_e2e/sys_call_test.h @@ -57,17 +57,19 @@ class sys_call_test : public testing::Test { protected: void SetUp() { - m_tid = getpid(); - m_tid_filter = [this](sinsp_evt* evt) { + m_pid = getpid(); + // Check that the event comes from a secondary thread inside the process, + // since the test callback is ran on an helper thread. + m_tid_filter = [&](sinsp_evt* evt) { if(evt->get_param_value_str("fd").find(LIBSINSP_TEST_KERNEL_MODULE_NAME) != std::string::npos) { return false; } - return evt->get_tid() == m_tid; + return evt->get_tid() > m_pid; }; }; - __pid_t m_tid; + __pid_t m_pid; event_filter_t m_tid_filter; }; diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index c5d9625ca2..36e11c85db 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -110,11 +110,9 @@ void runtest(iotype iot, // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->dynamic_snaplen(true); - } + before_open_t before = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; + + run_callback_t test = [&]() { server_proc.start(); server_proc.wait_for_start(); server_pid = server_proc.get_pid(); @@ -275,9 +273,8 @@ void runtest(iotype iot, event_capture::run(test, callback, filter, + before, event_capture::do_nothing, - event_capture::do_nothing, - event_capture::always_continue, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, @@ -347,7 +344,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { server.signal_continue(); client.signal_continue(); server_thread.join(); @@ -375,7 +372,6 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) filter, event_capture::do_nothing, event_capture::do_nothing, - event_capture::always_continue, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index c05561014f..b285c4e4b6 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -386,7 +386,7 @@ void runtest_ipv4m(iotype iot, // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { server_thread = std::thread(&tcp_server_ipv4m::run, server); server->wait_till_ready(); @@ -589,7 +589,6 @@ void runtest_ipv4m(iotype iot, filter, event_capture::do_nothing, event_capture::do_nothing, - event_capture::always_continue, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, @@ -646,7 +645,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts_ // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&]() { server.signal_continue(); client.signal_continue(); server_thread.join(); diff --git a/test/libsinsp_e2e/test_helper.cpp b/test/libsinsp_e2e/test_helper.cpp index 11764f22c7..d6d35be6c8 100644 --- a/test/libsinsp_e2e/test_helper.cpp +++ b/test/libsinsp_e2e/test_helper.cpp @@ -83,7 +83,7 @@ void mmap_test(const vector& args) { munmap(p, 1003520); printf("%d\n", errno2); fflush(stdout); - printf("%u\n", p); + printf("%p\n", p); fflush(stdout); } diff --git a/test/libsinsp_e2e/udp_client_server.cpp b/test/libsinsp_e2e/udp_client_server.cpp index 77b23247e2..9ea4684a36 100644 --- a/test/libsinsp_e2e/udp_client_server.cpp +++ b/test/libsinsp_e2e/udp_client_server.cpp @@ -469,7 +469,7 @@ TEST_F(sys_call_test, udp_client_server) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&]() { udps.start(); }; // // OUTPUT VALDATION @@ -598,7 +598,7 @@ TEST_F(sys_call_test, udp_client_server_with_connect_by_client) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&]() { udps.start(); }; // // OUTPUT VALDATION @@ -635,7 +635,7 @@ TEST_F(sys_call_test, udp_client_server_sendmsg) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&]() { udps.start(); }; // // OUTPUT VALDATION @@ -691,7 +691,7 @@ TEST_F(sys_call_test, udp_client_server_sendmsg_2buf) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&]() { udps.start(); }; // // OUTPUT VALDATION @@ -760,7 +760,7 @@ static void run_fd_name_changed_test(bool use_sendmsg, // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&]() { udps.start(); }; // // OUTPUT VALDATION @@ -837,7 +837,7 @@ TEST_F(sys_call_test, udp_client_server_multiple_connect_name_changed) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { int sd; sd = socket(AF_INET, SOCK_DGRAM, 0); @@ -904,7 +904,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { // sendto with addr udp_client client(0x0100007F, false, 8125); client.m_payload = payload; @@ -962,7 +962,7 @@ TEST_F(sys_call_test, statsd_client_no_snaplen) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&]() { // sendto with addr // Different port udp_client client(0x0100007F, false, 8126); diff --git a/test/libsinsp_e2e/unix_client_server.cpp b/test/libsinsp_e2e/unix_client_server.cpp index a668cb3e8a..0d9cacaf89 100644 --- a/test/libsinsp_e2e/unix_client_server.cpp +++ b/test/libsinsp_e2e/unix_client_server.cpp @@ -102,7 +102,7 @@ TEST_F(sys_call_test, unix_client_server) { // // INITIALIZATION // - run_callback_t test = [](concurrent_object_handle inspector) { + run_callback_t test = []() { subprocess server("python3", {LIBSINSP_TEST_RESOURCES_PATH "/unix_client_server.py", "server"}); From 5436e83afbbc8a4717582dacb29d151c3c66f9a6 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 26 Sep 2024 09:05:59 +0200 Subject: [PATCH 02/20] chore(test): run test synchronously on the same thread of capture unless the special `run_callback_async_t` is used. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/capture_to_file_test.cpp | 2 +- test/libsinsp_e2e/container/container.cpp | 20 +++--- test/libsinsp_e2e/event_capture.cpp | 54 -------------- test/libsinsp_e2e/event_capture.h | 52 +++++++++----- test/libsinsp_e2e/forking.cpp | 44 ++++++------ test/libsinsp_e2e/fs.cpp | 32 ++++----- test/libsinsp_e2e/paths.cpp | 6 +- test/libsinsp_e2e/process.cpp | 36 ++++------ test/libsinsp_e2e/suppress_events.cpp | 8 +-- test/libsinsp_e2e/sys_call_test.cpp | 70 +++++++++---------- test/libsinsp_e2e/sys_call_test.h | 2 +- test/libsinsp_e2e/tcp_client_server.cpp | 4 +- .../tcp_client_server_ipv4_mapped.cpp | 4 +- test/libsinsp_e2e/udp_client_server.cpp | 16 ++--- test/libsinsp_e2e/unix_client_server.cpp | 2 +- 15 files changed, 152 insertions(+), 200 deletions(-) diff --git a/test/libsinsp_e2e/capture_to_file_test.cpp b/test/libsinsp_e2e/capture_to_file_test.cpp index 4e73fb00fa..dbe4c4d713 100644 --- a/test/libsinsp_e2e/capture_to_file_test.cpp +++ b/test/libsinsp_e2e/capture_to_file_test.cpp @@ -32,7 +32,7 @@ TEST_F(sys_call_test, can_consume_a_capture_file) { evt->get_direction() == SCAP_ED_OUT; }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { struct stat sb; for(int i = 0; i < 100; i++) { stat("/tmp", &sb); diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 6ed4a886b7..06ac536eba 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -27,7 +27,7 @@ limitations under the License. using namespace std; TEST_F(sys_call_test, container_cgroups) { - int ctid = -1; + int ctid; bool done = false; // @@ -40,7 +40,7 @@ TEST_F(sys_call_test, container_cgroups) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_async_t test = [&]() { ctid = fork(); if(ctid >= 0) { if(ctid == 0) { @@ -134,7 +134,7 @@ TEST_F(sys_call_test, container_clone_nspid) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stack_top; /* End of stack buffer area */ @@ -204,7 +204,7 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { // // TEST CODE // - run_callback_t test = [&]() { waitpid(ctid, NULL, 0); }; + run_callback_t test = [&](sinsp* inspector) { waitpid(ctid, NULL, 0); }; // // OUTPUT VALDATION @@ -234,7 +234,7 @@ static void run_container_docker_test(bool fork_after_container_start) { evt->get_type() == PPME_CONTAINER_JSON_2_E); }; - run_callback_t test = [&]() { + run_callback_async_t test = [&]() { ASSERT_TRUE(system("docker kill libsinsp_docker > /dev/null 2>&1 || true") == 0); ASSERT_TRUE(system("docker rm -v libsinsp_docker > /dev/null 2>&1 || true") == 0); @@ -342,7 +342,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { return false; }; - run_callback_t test = [&]() { + run_callback_async_t test = []() { ASSERT_TRUE(system("docker kill libsinsp_docker > /dev/null 2>&1 || true") == 0); ASSERT_TRUE(system("docker rm -v libsinsp_docker > /dev/null 2>&1 || true") == 0); @@ -404,7 +404,7 @@ TEST_F(sys_call_test, container_libvirt) { return false; }; - run_callback_t test = [&]() { + run_callback_async_t test = [&]() { FILE* f = fopen("/tmp/conf.xml", "w"); ASSERT_TRUE(f != NULL); fprintf(f, @@ -607,7 +607,7 @@ static void healthcheck_helper( evt->get_direction() == SCAP_ED_OUT && !tinfo->m_container_id.empty()); }; - run_callback_t test = [&]() { + run_callback_async_t test = [&]() { int rc = dhelper.run_container("cont_health_ut", "/bin/sh -c '/bin/sleep 10'"); ASSERT_TRUE(exited_early || (rc == 0)); @@ -650,7 +650,7 @@ static void healthcheck_tracefile_helper( dockerfile + " . > /dev/null 2>&1"); ASSERT_TRUE(system(build_cmdline.c_str()) == 0); - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { // --network=none speeds up the container setup a bit. ASSERT_TRUE( (system("docker run --rm --network=none --name cont_health_ut cont_health_ut_img " @@ -821,7 +821,7 @@ TEST_F(sys_call_test, docker_container_large_json) { evt->get_type() == PPME_CONTAINER_JSON_2_E; }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int rc = dhelper.run_container("large_container_ut", "/bin/sh -c '/bin/sleep 3'"); ASSERT_TRUE(rc == 0); diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 9ffdb38ec5..b2c20e1aa7 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -29,7 +29,6 @@ limitations under the License. std::string event_capture::s_engine_string = KMOD_ENGINE; std::string event_capture::s_engine_path; unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; -int event_capture::s_eventfd = -1; event_capture::event_capture(sinsp_mode_t mode, captured_event_callback_t captured_event_callback, @@ -48,7 +47,6 @@ event_capture::event_capture(sinsp_mode_t mode, m_filter = std::move(filter); m_max_timeouts = max_timeouts; - s_eventfd = eventfd(0, EFD_NONBLOCK); m_inspector = std::make_unique(); m_inspector->m_thread_manager->set_max_thread_table_size(max_thread_table_size); m_inspector->m_thread_timeout_ns = thread_timeout_ns; @@ -61,11 +59,6 @@ event_capture::event_capture(sinsp_mode_t mode, m_param.m_inspector = m_inspector.get(); } -event_capture::~event_capture() { - close(s_eventfd); - s_eventfd = -1; -} - void event_capture::start(bool dump) { open_engine(event_capture::get_engine(), {}); @@ -104,10 +97,6 @@ void event_capture::capture() { uint32_t n_timeouts = 0; while(result && !::testing::Test::HasFatalFailure()) { - if(handle_request()) { - continue; - } - next_result = m_inspector->next(&event); if(next_result == SCAP_TIMEOUT) { n_timeouts++; @@ -132,43 +121,6 @@ void event_capture::capture() { } } -// Returns true if the current iteration can be skipped -bool event_capture::handle_request() { - eventfd_t req; - int ret = eventfd_read(s_eventfd, &req); - if(ret == 0) { - // manage request - switch(req) { - case E2E_REQ_STOP_CAPTURE: { - m_inspector->stop_capture(); - int oldfl; - oldfl = fcntl(s_eventfd, F_GETFL); - // Drop the nonblock mode on the FD to avoid busy loop; - // instead, main loop will block until start_capture is requested - fcntl(s_eventfd, F_SETFL, oldfl & ~O_NONBLOCK); - return true; - } - case E2E_REQ_START_CAPTURE: { - m_inspector->start_capture(); - int oldfl; - oldfl = fcntl(s_eventfd, F_GETFL); - // Reset the O_NONBLOCK flag to avoid the blocking read from the eventfd. - fcntl(s_eventfd, F_SETFL, oldfl | O_NONBLOCK); - break; - } - case E2E_REQ_SUPPRESS_SH: - m_inspector->suppress_events_comm("test_helper.sh"); - break; - case E2E_REQ_SUPPRESS: - m_inspector->suppress_events_comm("test_helper"); - break; - default: - break; - } - } - return false; -} - bool event_capture::handle_event(sinsp_evt* event) { bool res = true; @@ -242,9 +194,3 @@ const std::string& event_capture::get_engine() { const std::string& event_capture::get_engine_path() { return s_engine_path; } - -void event_capture::do_request(e2e_req_t req) { - eventfd_write(s_eventfd, req); - // Wait for the request to be caught by the main thread - usleep(50); -} diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index 75910b29b8..72a256fee7 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -39,14 +39,6 @@ limitations under the License. // that we received all events from the driver, until this very last close(FD_SIGNAL_STOP); #define FD_SIGNAL_STOP 555 -// eventfd inter-thread requests -typedef enum : std::uint8_t { - E2E_REQ_STOP_CAPTURE = 1, - E2E_REQ_START_CAPTURE = 2, - E2E_REQ_SUPPRESS_SH = 3, - E2E_REQ_SUPPRESS = 4, -} e2e_req_t; - class callback_param { public: sinsp_evt* m_evt; @@ -57,8 +49,8 @@ typedef std::function before_open_t; typedef std::function before_close_t; typedef std::function event_filter_t; typedef std::function captured_event_callback_t; - -typedef std::function run_callback_t; +typedef std::function run_callback_t; +typedef std::function run_callback_async_t; class event_capture { public: @@ -71,7 +63,6 @@ class event_capture { uint64_t thread_timeout_ns, uint64_t inactive_thread_scan_time_ns, uint64_t max_timeouts); - ~event_capture(); void start(bool dump); void stop(); @@ -79,7 +70,39 @@ class event_capture { static void do_nothing(sinsp* inspector) {} - static void run(run_callback_t run_function, + static void run(const run_callback_t& run_function, + captured_event_callback_t captured_event_callback, + event_filter_t filter, + before_open_t before_open = event_capture::do_nothing, + before_close_t before_close = event_capture::do_nothing, + uint32_t max_thread_table_size = 131072, + uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, + uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, + sinsp_mode_t mode = SINSP_MODE_LIVE, + uint64_t max_timeouts = 3, + bool dump = true) { + event_capture capturing(mode, + std::move(captured_event_callback), + std::move(before_open), + std::move(before_close), + std::move(filter), + max_thread_table_size, + thread_timeout_ns, + inactive_thread_scan_time_ns, + max_timeouts); + + capturing.start(dump); + + run_function(capturing.m_inspector.get()); + // signal main thread to end the capture + close(FD_SIGNAL_STOP); + + capturing.capture(); + + capturing.stop(); + } + + static void run(const run_callback_async_t& run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, before_open_t before_open = event_capture::do_nothing, @@ -115,8 +138,6 @@ class event_capture { capturing.stop(); } - static void do_request(e2e_req_t req); - static void set_engine(const std::string& engine_string, const std::string& engine_path); static const std::string& get_engine(); static void set_buffer_dim(const unsigned long& dim); @@ -126,7 +147,6 @@ class event_capture { static unsigned long s_buffer_dim; private: - bool handle_request(); bool handle_event(sinsp_evt* event); void open_engine(const std::string& engine_string, @@ -141,6 +161,4 @@ class event_capture { callback_param m_param{}; sinsp_mode_t m_mode; uint64_t m_max_timeouts{}; - - static int s_eventfd; }; diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 1da5674779..63442eb745 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -57,7 +57,7 @@ TEST_F(sys_call_test, forking) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { pid_t childtid; int status; childtid = fork(); @@ -107,19 +107,17 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { return evt->get_tid() == ptid || evt->get_tid() == ctid; }; - before_open_t before = [&](sinsp* inspector) { - // - // Stop the capture just before the fork so we lose the event. - // - inspector->stop_capture(); - }; - // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int status; + // + // Stop the capture just before the fork so we lose the event. + // + inspector->stop_capture(); + ctid = fork(); int fd = creat(FILENAME, S_IRWXU); @@ -137,7 +135,7 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { // It's a simple way to make sure the capture is started // after the child's clone returned. // - event_capture::do_request(E2E_REQ_START_CAPTURE); + inspector->start_capture(); // // Wait for 5 seconds to make sure the process will still @@ -196,7 +194,7 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); EXPECT_TRUE(child_exists); EXPECT_TRUE(parent_exists); @@ -221,7 +219,7 @@ TEST_F(sys_call_test, forking_process_expired) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { ctid = fork(); if(ctid >= 0) // fork succeeded @@ -348,7 +346,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ @@ -483,7 +481,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ @@ -620,7 +618,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ @@ -708,7 +706,7 @@ TEST_F(sys_call_test, forking_main_thread_exit) { } }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int status; // ptid = getpid(); @@ -780,7 +778,9 @@ static int stop_sinsp_and_exit(void* arg) { return 1; } - event_capture::do_request(E2E_REQ_STOP_CAPTURE); + sinsp* inspector = (sinsp*)arg; + + inspector->stop_capture(); // Wait 5 seconds. This ensures that the state for this // process will be considered stale when the second process @@ -872,7 +872,7 @@ static pid_t clone_helper(int (*func)(void*), } TEST_F(sys_call_test, remove_stale_thread_clone_exit) { - std::atomic clones_seen(0); + uint32_t clones_seen = 0; stale_clone_ctx ctx; std::atomic recycle_pid(0); const char* last_pid_filename = "/proc/sys/kernel/ns_last_pid"; @@ -901,7 +901,7 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { return (rp != 0 && tinfo && tinfo->m_tid == rp); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { pid_t launcher_pid; char* launcher_stack = NULL; @@ -921,11 +921,9 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { recycle_pid.store(clone_helper(stop_sinsp_and_exit, nullptr)); ASSERT_GE(recycle_pid.load(), 0); - usleep(500); - // The first thread has started, turned off the capturing, and // exited, so start capturing again. - event_capture::do_request(E2E_REQ_START_CAPTURE); + inspector->start_capture(); // Arrange that the next thread/process created has // pid ctx.m_desired pid by writing to @@ -1002,5 +1000,5 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // We must have seen one clone related to the recycled // pid. Otherwise it never actually checked the cwd at all. - EXPECT_EQ(clones_seen.load(), 1u); + EXPECT_EQ(clones_seen, 1u); } diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index b51ec90f39..e0d53d40d4 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -69,7 +69,7 @@ TEST_F(sys_call_test, fs_creat_ulink) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int fd = creat(FILENAME, 0644); if(fd < 0) { @@ -158,7 +158,7 @@ TEST_F(sys_call_test, fs_mkdir_rmdir) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { mkdir(UNEXISTENT_DIRNAME, 0); if(mkdir(DIRNAME, 0) != 0) { @@ -262,7 +262,7 @@ TEST_F(sys_call_test, fs_openat) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { dirfd = open(".", O_DIRECTORY); if(dirfd <= 0) { FAIL(); @@ -341,7 +341,7 @@ TEST_F(sys_call_test, fs_pread) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { fd = creat(FILENAME, S_IRWXU); if(fd < 0) { FAIL(); @@ -467,7 +467,7 @@ TEST_F(sys_call_test, fs_readv) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int wv_count; char msg1[10] = "aaaaa"; char msg2[10] = "bbbbb"; @@ -561,7 +561,7 @@ TEST_F(sys_call_test, fs_preadv) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int wv_count; char msg1[10] = "aaaaa"; char msg2[10] = "bbbbb"; @@ -698,7 +698,7 @@ TEST_F(sys_call_test, fs_dup) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { fd = open(FILENAME, O_CREAT | O_WRONLY, 0); fd1 = dup(fd); fd2 = dup2(fd, 333); @@ -823,7 +823,7 @@ TEST_F(sys_call_test, fs_fcntl) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { fd = open(FILENAME, O_CREAT | O_WRONLY, 0); fd1 = fcntl(fd, F_DUPFD, 0); fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 0); @@ -897,7 +897,7 @@ TEST_F(sys_call_test, fs_sendfile) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -955,7 +955,7 @@ TEST_F(sys_call_test, fs_sendfile_nulloff) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1011,7 +1011,7 @@ TEST_F(sys_call_test, fs_sendfile_failed) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int res = sendfile(-1, -2, NULL, 444); EXPECT_GT(0, res); }; @@ -1060,7 +1060,7 @@ TEST_F(sys_call_test, fs_sendfile_invalidoff) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1120,7 +1120,7 @@ TEST_F(sys_call_test, fs_sendfile64) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1178,7 +1178,7 @@ TEST_F(sys_call_test, large_read_write) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { fd1 = creat(FILENAME, S_IRWXU); if(fd1 < 0) { FAIL(); @@ -1274,7 +1274,7 @@ TEST_F(sys_call_test, large_readv_writev) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { fd = creat(FILENAME, S_IRWXU); if(fd < 0) { FAIL(); @@ -1392,7 +1392,7 @@ TEST_F(sys_call_test, large_open) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { #ifdef SYS_open int fd = syscall(SYS_open, buf.c_str(), O_RDONLY); #else diff --git a/test/libsinsp_e2e/paths.cpp b/test/libsinsp_e2e/paths.cpp index bdbd80583d..c681b869ac 100644 --- a/test/libsinsp_e2e/paths.cpp +++ b/test/libsinsp_e2e/paths.cpp @@ -131,7 +131,7 @@ void testdir(string filename, string chdirtarget = "") { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { tid = gettid(); if(!chdirtarget.empty()) { char tcwd[1024]; @@ -422,7 +422,7 @@ TEST_F(sys_call_test, dir_getcwd) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { ASSERT_TRUE(chdir(dir0) == 0); ASSERT_TRUE(getcwd(cwd0, 256) != NULL); @@ -541,7 +541,7 @@ TEST_F(sys_call_test, dir_fchdir) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int fd; fd = open(dir0, O_RDONLY); diff --git a/test/libsinsp_e2e/process.cpp b/test/libsinsp_e2e/process.cpp index ec0ba53b51..d65cdfcb0a 100644 --- a/test/libsinsp_e2e/process.cpp +++ b/test/libsinsp_e2e/process.cpp @@ -68,7 +68,7 @@ TEST_F(sys_call_test, process_signalfd_kill) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int status; int sfd; ctid = fork(); @@ -219,7 +219,7 @@ TEST_F(sys_call_test, DISABLED_process_usleep) { // // TEST CODE // - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { struct timespec req; req.tv_sec = 0; req.tv_nsec = 123456; @@ -271,7 +271,7 @@ TEST_F(sys_call_test, process_inotify) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int length; int wd; char buffer[EVENT_BUF_LEN]; @@ -288,9 +288,9 @@ TEST_F(sys_call_test, process_inotify) { // // The IN_MODIFY flag causes a notification when a file is written, which should - // heppen immediately in captures + // happen immediately under /proc/ // - wd = inotify_add_watch(fd, LIBSINSP_TEST_CAPTURES_PATH, IN_MODIFY | IN_CREATE | IN_OPEN); + wd = inotify_add_watch(fd, "/proc/", IN_MODIFY | IN_CREATE | IN_OPEN); // // read to determine the event changes @@ -387,7 +387,7 @@ TEST_F(sys_call_test, process_rlimit) { // // TEST CODE // - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { struct rlimit rl; sleep(1); @@ -498,7 +498,7 @@ TEST_F(sys_call_test, process_prlimit) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { struct rlimit newrl; struct rlimit oldrl; @@ -617,7 +617,7 @@ TEST_F(sys_call_test, process_scap_proc_get) { // // TEST CODE // - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { usleep(1000); int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -715,7 +715,7 @@ TEST_F(sys_call_test, procinfo_processchild_cpuload) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { for(uint32_t j = 0; j < 5; j++) { sleep(1); } @@ -737,11 +737,7 @@ TEST_F(sys_call_test, procinfo_processchild_cpuload) { if(tinfo) { if(tinfo->m_tid == ctid) { - uint64_t tcpu; - - const sinsp_evt_param* parinfo = e->get_param(0); - // tcpu = *(uint64_t*)parinfo->m_val; - memcpy(&tcpu, parinfo->m_val, sizeof(uint64_t)); + auto tcpu = e->get_param(0)->as(); uint64_t delta = tcpu - lastcpu; @@ -786,7 +782,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { for(uint32_t j = 0; j < 5; j++) { sleep(1); } @@ -810,10 +806,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { if(tinfo) { if(tinfo->m_tid == ctid) { - uint64_t tcpu; - - const sinsp_evt_param* parinfo = e->get_param(0); - tcpu = *(uint64_t*)parinfo->m_val; + auto tcpu = e->get_param(0)->as(); uint64_t delta = tcpu - lastcpu; @@ -826,10 +819,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { callnum++; } else if(tinfo->m_tid == ctid1) { - uint64_t tcpu; - - const sinsp_evt_param* parinfo = e->get_param(0); - tcpu = *(uint64_t*)parinfo->m_val; + auto tcpu = e->get_param(0)->as(); uint64_t delta = tcpu - lastcpu1; diff --git a/test/libsinsp_e2e/suppress_events.cpp b/test/libsinsp_e2e/suppress_events.cpp index 1cae5aef2c..a922307748 100644 --- a/test/libsinsp_e2e/suppress_events.cpp +++ b/test/libsinsp_e2e/suppress_events.cpp @@ -61,10 +61,10 @@ static void test_helper_quotactl(test_helper_args& hargs) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { if(!hargs.suppress_before) { - event_capture::do_request(hargs.spawn_with_bash ? E2E_REQ_SUPPRESS_SH - : E2E_REQ_SUPPRESS); + inspector->suppress_events_comm( + std::string((hargs.spawn_with_bash ? "test_helper.sh" : "test_helper"))); } if(!hargs.start_before) { @@ -276,7 +276,7 @@ void suppress_types::run_test(std::vector supp_syscalls) { // // TEST CODE // - run_callback_t test = [&]() { do_syscalls(); }; + run_callback_t test = [&](sinsp* inspector) { do_syscalls(); }; // // OUTPUT VALDATION diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index 2af23ba379..66bdd7245b 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -95,7 +95,7 @@ TEST_F(sys_call_test, stat) { return evt_name.find("stat") != std::string::npos && m_tid_filter(evt); }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { struct stat sb; stat("/tmp", &sb); }; @@ -114,7 +114,7 @@ TEST_F(sys_call_test, open_close) { m_tid_filter(evt); }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { int fd = open("/tmp", O_RDONLY); close(fd); }; @@ -143,7 +143,7 @@ TEST_F(sys_call_test, open_close_dropping) { m_tid_filter(evt); }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { int fd = open("/tmp", O_RDONLY); close(fd); }; @@ -170,7 +170,7 @@ TEST_F(sys_call_test, fcntl_getfd) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); }; - run_callback_t test = []() { fcntl(0, F_GETFL); }; + run_callback_t test = [](sinsp* inspector) { fcntl(0, F_GETFL); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -187,7 +187,7 @@ TEST_F(sys_call_test, fcntl_getfd_dropping) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); }; - run_callback_t test = []() { fcntl(0, F_GETFL); }; + run_callback_t test = [](sinsp* inspector) { fcntl(0, F_GETFL); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -203,7 +203,7 @@ TEST_F(sys_call_test, bind_error) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); }; - run_callback_t test = []() { bind(0, NULL, 0); }; + run_callback_t test = [](sinsp* inspector) { bind(0, NULL, 0); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -220,7 +220,7 @@ TEST_F(sys_call_test, bind_error_dropping) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); }; - run_callback_t test = []() { bind(0, NULL, 0); }; + run_callback_t test = [](sinsp* inspector) { bind(0, NULL, 0); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -236,7 +236,7 @@ TEST_F(sys_call_test, close_badfd) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { close(-1); close(INT_MAX); }; @@ -263,7 +263,7 @@ TEST_F(sys_call_test, close_badfd_dropping) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { close(-1); close(INT_MAX); }; @@ -297,7 +297,7 @@ TEST_F(sys_call_test, poll_timeout) { std::string my_pipe[2]; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper", {"poll_timeout"}); std::stringstream ss; ss << handle.out(); @@ -368,7 +368,7 @@ TEST_F(sys_call_test, ioctl) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int status; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int fd; fd = open("/dev/ttyS0", O_RDONLY); @@ -405,7 +405,7 @@ TEST_F(sys_call_test, shutdown) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int sock; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { FAIL() << "socket() failed"; return; @@ -451,7 +451,7 @@ TEST_F(sys_call_test, timerfd) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int fd; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int ret; unsigned int ns; unsigned int sec; @@ -517,7 +517,7 @@ TEST_F(sys_call_test, timestamp) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { useconds_t sleep_period = 10; struct timeval tv; for(uint32_t j = 0; j < sizeof(timestampv) / sizeof(timestampv[0]); ++j) { @@ -546,7 +546,7 @@ TEST_F(sys_call_test, brk) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { sbrk(1000); sbrk(100000); }; @@ -608,7 +608,7 @@ TEST_F(sys_call_test, mmap) { void* p; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { munmap((void*)0x50, 300); p = mmap(0, 0, @@ -762,7 +762,7 @@ TEST_F(sys_call_test, quotactl_ko) { evt->get_type() == PPME_SYSCALL_QUOTACTL_E; }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { quotactl(QCMD(Q_QUOTAON, USRQUOTA), "/dev/xxx", 2, @@ -831,7 +831,7 @@ TEST_F(sys_call_test, quotactl_ok) { struct dqblk mydqblk; struct dqinfo mydqinfo; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { quotactl(QCMD(Q_QUOTAON, USRQUOTA), "/dev/loop0", 2, @@ -931,7 +931,7 @@ TEST_F(sys_call_test, getsetuid_and_gid) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { auto res = setuid(0); EXPECT_EQ(0, res); res = setgid(test_gid); @@ -1024,7 +1024,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) { event_filter_t filter = [&](sinsp_evt* evt) { return is_subprocess_execve->run(evt); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { auto ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32 " LIBSINSP_TEST_RESOURCES_PATH "execve " LIBSINSP_TEST_RESOURCES_PATH "execve32"); @@ -1085,7 +1085,7 @@ TEST_F(sys_call_test32, quotactl_ko) { evt->get_type() == PPME_SYSCALL_QUOTACTL_E; }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", {"quotactl_ko"}); handle.wait(); }; @@ -1132,7 +1132,7 @@ TEST_F(sys_call_test, setns_test) { return m_tid_filter(evt) && (evt->get_type() == PPME_SYSCALL_SETNS_E || evt->get_type() == PPME_SYSCALL_SETNS_X); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { fd = open("/proc/self/ns/net", O_RDONLY); ASSERT_NE(0, fd); ASSERT_EQ(0, setns(fd, CLONE_NEWNET)); @@ -1163,7 +1163,7 @@ TEST_F(sys_call_test, unshare_) { (evt->get_type() == PPME_SYSCALL_UNSHARE_E || evt->get_type() == PPME_SYSCALL_UNSHARE_X); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { auto child = fork(); if(child == 0) { unshare(CLONE_NEWUTS); @@ -1195,7 +1195,7 @@ TEST_F(sys_call_test, sendmsg_recvmsg_SCM_RIGHTS) { auto tinfo = evt->get_thread_info(true); return tinfo->get_comm() == "libsinsp_e2e_te" && evt->get_type() == PPME_SOCKET_RECVMSG_X; }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int server_sd, worker_sd, pair_sd[2]; int rc = socketpair(AF_UNIX, SOCK_DGRAM, 0, pair_sd); ASSERT_GE(rc, 0); @@ -1282,7 +1282,7 @@ TEST_F(sys_call_test, ppoll_timeout) { ti->m_comm == "test_helper"; }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper", {"ppoll_timeout"}); handle.wait(); }; @@ -1365,7 +1365,7 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { char command[] = "useradd -u 5454 testsetresuid && " "groupadd -g 6565 testsetresgid && " @@ -1476,7 +1476,7 @@ TEST_F(sys_call_test, failing_execve) { printf("%s %s %s %s %s\n", eargv[0], eargv[1], eargv[2], eargv[3], eargv[4]); printf("%s %s %s %s\n", eenvp[0], eenvp[1], eenvp[2], eenvp[3]); - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int ret = execve(eargv[0], (char* const*)eargv, (char* const*)eenvp); ASSERT_TRUE(ret < 0); }; @@ -1529,7 +1529,7 @@ TEST_F(sys_call_test, large_execve) { buf.append(std::to_string(random())); } - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { ctid = fork(); if(ctid < 0) { @@ -1629,7 +1629,7 @@ TEST_F(sys_call_test32, failing_execve) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { auto ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32_fail"); ASSERT_TRUE(ret > 0); ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32 ./fail"); @@ -1724,7 +1724,7 @@ TEST_F(sys_call_test32, mmap) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", { "mmap_test", @@ -1881,7 +1881,7 @@ TEST_F(sys_call_test32, ppoll_timeout) { std::string my_pipe[2]; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", { "ppoll_timeout", @@ -1968,7 +1968,7 @@ TEST_F(sys_call_test32, fs_preadv) { // // TEST CODE // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { subprocess test_proc(LIBSINSP_TEST_PATH "/test_helper_32", {"preadv_pwritev"}); fd = std::stoi(test_proc.out()); int bool_n = std::stoi(test_proc.out()); @@ -2067,7 +2067,7 @@ TEST_F(sys_call_test, thread_lookup_static) { event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() != PPME_PROCEXIT_1_E && evt->get_tid() > 0; }; - run_callback_t test = [&]() { return; }; + run_callback_t test = [&](sinsp* inspector) { return; }; captured_event_callback_t callback = [&](const callback_param& param) { auto* platform = (scap_linux_platform*)param.m_inspector->get_scap_platform(); ASSERT_EQ(SCAP_SUCCESS, @@ -2106,7 +2106,7 @@ TEST_F(sys_call_test, thread_lookup_live) { event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() != PPME_PROCEXIT_1_E && evt->get_tid() > 0; }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { // a very short sleep to gather some events, // we'll take much longer than this to process them all usleep(1000); @@ -2176,7 +2176,7 @@ TEST_F(sys_call_test, fd_name_max_path) { m_tid_filter(evt); }; - run_callback_t test = [&]() { open(pathname.c_str(), O_RDONLY); }; + run_callback_t test = [&](sinsp* inspector) { open(pathname.c_str(), O_RDONLY); }; sinsp_filter_check_list m_filterlist; diff --git a/test/libsinsp_e2e/sys_call_test.h b/test/libsinsp_e2e/sys_call_test.h index 8a03e8a91f..2248f8b4a3 100644 --- a/test/libsinsp_e2e/sys_call_test.h +++ b/test/libsinsp_e2e/sys_call_test.h @@ -65,7 +65,7 @@ class sys_call_test : public testing::Test { std::string::npos) { return false; } - return evt->get_tid() > m_pid; + return evt->get_tid() == m_pid; }; }; diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index 36e11c85db..712d47773d 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -112,7 +112,7 @@ void runtest(iotype iot, // before_open_t before = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { server_proc.start(); server_proc.wait_for_start(); server_pid = server_proc.get_pid(); @@ -344,7 +344,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) // // INITIALIZATION // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { server.signal_continue(); client.signal_continue(); server_thread.join(); diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index b285c4e4b6..c8a9c3769a 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -386,7 +386,7 @@ void runtest_ipv4m(iotype iot, // // INITIALIZATION // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { server_thread = std::thread(&tcp_server_ipv4m::run, server); server->wait_till_ready(); @@ -645,7 +645,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts_ // // INITIALIZATION // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { server.signal_continue(); client.signal_continue(); server_thread.join(); diff --git a/test/libsinsp_e2e/udp_client_server.cpp b/test/libsinsp_e2e/udp_client_server.cpp index 9ea4684a36..4ab4e7ef4d 100644 --- a/test/libsinsp_e2e/udp_client_server.cpp +++ b/test/libsinsp_e2e/udp_client_server.cpp @@ -469,7 +469,7 @@ TEST_F(sys_call_test, udp_client_server) { // // INITIALIZATION // - run_callback_t test = [&]() { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -598,7 +598,7 @@ TEST_F(sys_call_test, udp_client_server_with_connect_by_client) { // // INITIALIZATION // - run_callback_t test = [&]() { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -635,7 +635,7 @@ TEST_F(sys_call_test, udp_client_server_sendmsg) { // // INITIALIZATION // - run_callback_t test = [&]() { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -691,7 +691,7 @@ TEST_F(sys_call_test, udp_client_server_sendmsg_2buf) { // // INITIALIZATION // - run_callback_t test = [&]() { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -760,7 +760,7 @@ static void run_fd_name_changed_test(bool use_sendmsg, // // INITIALIZATION // - run_callback_t test = [&]() { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -837,7 +837,7 @@ TEST_F(sys_call_test, udp_client_server_multiple_connect_name_changed) { // // INITIALIZATION // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { int sd; sd = socket(AF_INET, SOCK_DGRAM, 0); @@ -904,7 +904,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { // // INITIALIZATION // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { // sendto with addr udp_client client(0x0100007F, false, 8125); client.m_payload = payload; @@ -962,7 +962,7 @@ TEST_F(sys_call_test, statsd_client_no_snaplen) { // // INITIALIZATION // - run_callback_t test = [&]() { + run_callback_t test = [&](sinsp* inspector) { // sendto with addr // Different port udp_client client(0x0100007F, false, 8126); diff --git a/test/libsinsp_e2e/unix_client_server.cpp b/test/libsinsp_e2e/unix_client_server.cpp index 0d9cacaf89..a501b66f90 100644 --- a/test/libsinsp_e2e/unix_client_server.cpp +++ b/test/libsinsp_e2e/unix_client_server.cpp @@ -102,7 +102,7 @@ TEST_F(sys_call_test, unix_client_server) { // // INITIALIZATION // - run_callback_t test = []() { + run_callback_t test = [](sinsp* inspector) { subprocess server("python3", {LIBSINSP_TEST_RESOURCES_PATH "/unix_client_server.py", "server"}); From fc675a13791d9bf55302fa8a431121f84fed4203 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 26 Sep 2024 12:01:27 +0200 Subject: [PATCH 03/20] chore(test/libsinsp_e2e): more fixes. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 8 ++--- test/libsinsp_e2e/event_capture.cpp | 31 +++++-------------- test/libsinsp_e2e/event_capture.h | 13 ++------ test/libsinsp_e2e/fs.cpp | 10 ++---- test/libsinsp_e2e/sys_call_test.cpp | 25 ++++++--------- test/libsinsp_e2e/tcp_client_server.cpp | 2 -- .../tcp_client_server_ipv4_mapped.cpp | 1 - test/libsinsp_e2e/udp_client_server.cpp | 4 +-- 8 files changed, 25 insertions(+), 69 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 06ac536eba..af674ad163 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -333,6 +333,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { event_filter_t filter = [&](sinsp_evt* evt) { if(evt->get_type() == PPME_CONTAINER_JSON_E || evt->get_type() == PPME_CONTAINER_JSON_2_E) { + printf("top container json\n"); return true; } auto tinfo = evt->get_thread_info(); @@ -379,11 +380,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { } }; - before_close_t cleanup = [&](sinsp* inspector) { - inspector->set_docker_socket_path("/var/run/docker.sock"); - }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); ASSERT_TRUE(done); } @@ -627,7 +624,6 @@ static void healthcheck_helper( before_close_t cleanup = [&](sinsp* inspector) { capture_stats_str = capture_stats(inspector); - inspector->stop_dropping_mode(); }; ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index b2c20e1aa7..4f8f76a19d 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -37,15 +37,13 @@ event_capture::event_capture(sinsp_mode_t mode, event_filter_t filter, uint32_t max_thread_table_size, uint64_t thread_timeout_ns, - uint64_t inactive_thread_scan_time_ns, - uint64_t max_timeouts) { + uint64_t inactive_thread_scan_time_ns) { m_mode = mode; m_captured_event_callback = std::move(captured_event_callback); m_before_open = std::move(before_open); m_before_close = std::move(before_close); m_filter = std::move(filter); - m_max_timeouts = max_timeouts; m_inspector = std::make_unique(); m_inspector->m_thread_manager->set_max_thread_table_size(max_thread_table_size); @@ -81,13 +79,12 @@ void event_capture::start(bool dump) { } void event_capture::stop() { - // Begin teardown synchronized section - m_before_close(m_inspector.get()); - m_inspector->stop_capture(); + m_before_close(m_inspector.get()); if(m_dumper != nullptr) { m_dumper->close(); } + m_inspector->close(); } void event_capture::capture() { @@ -95,29 +92,17 @@ void event_capture::capture() { bool result = true; int32_t next_result = SCAP_SUCCESS; - uint32_t n_timeouts = 0; while(result && !::testing::Test::HasFatalFailure()) { next_result = m_inspector->next(&event); - if(next_result == SCAP_TIMEOUT) { - n_timeouts++; - - if(n_timeouts < m_max_timeouts) { - continue; - } else { - break; - } - } - if(next_result == SCAP_FILTERED_EVENT) { continue; } - if(next_result != SCAP_SUCCESS) { - break; - } - if(m_dumper != nullptr) { - m_dumper->dump(event); + if(next_result == SCAP_SUCCESS) { + if(m_dumper != nullptr) { + m_dumper->dump(event); + } + result = handle_event(event); } - result = handle_event(event); } } diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index 72a256fee7..e936441710 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -61,8 +61,7 @@ class event_capture { event_filter_t filter, uint32_t max_thread_table_size, uint64_t thread_timeout_ns, - uint64_t inactive_thread_scan_time_ns, - uint64_t max_timeouts); + uint64_t inactive_thread_scan_time_ns); void start(bool dump); void stop(); @@ -79,7 +78,6 @@ class event_capture { uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, sinsp_mode_t mode = SINSP_MODE_LIVE, - uint64_t max_timeouts = 3, bool dump = true) { event_capture capturing(mode, std::move(captured_event_callback), @@ -88,8 +86,7 @@ class event_capture { std::move(filter), max_thread_table_size, thread_timeout_ns, - inactive_thread_scan_time_ns, - max_timeouts); + inactive_thread_scan_time_ns); capturing.start(dump); @@ -111,7 +108,6 @@ class event_capture { uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, sinsp_mode_t mode = SINSP_MODE_LIVE, - uint64_t max_timeouts = 3, bool dump = true) { event_capture capturing(mode, std::move(captured_event_callback), @@ -120,13 +116,11 @@ class event_capture { std::move(filter), max_thread_table_size, thread_timeout_ns, - inactive_thread_scan_time_ns, - max_timeouts); + inactive_thread_scan_time_ns); capturing.start(dump); std::thread thread([&run_function]() { - usleep(50); run_function(); // signal main thread to end the capture close(FD_SIGNAL_STOP); @@ -160,5 +154,4 @@ class event_capture { before_close_t m_before_close; callback_param m_param{}; sinsp_mode_t m_mode; - uint64_t m_max_timeouts{}; }; diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index e0d53d40d4..c460f8fb1f 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -1236,20 +1236,17 @@ TEST_F(sys_call_test, large_read_write) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->set_snaplen(DEFAULT_SNAPLEN); }; - // We don't dump events to scap files, otherwise we could stuck with modern bpf. ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, - cleanup, + event_capture::do_nothing, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, SINSP_MODE_LIVE, - 3, false); }); @@ -1358,20 +1355,17 @@ TEST_F(sys_call_test, large_readv_writev) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->set_snaplen(DEFAULT_SNAPLEN); }; - // We don't dump events to scap files, otherwise we could stuck with modern bpf. ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, - cleanup, + event_capture::do_nothing, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, SINSP_MODE_LIVE, - 3, false); }); diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index 66bdd7245b..054cce6052 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -157,9 +157,7 @@ TEST_F(sys_call_test, open_close_dropping) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(2, callnum); } @@ -181,7 +179,7 @@ TEST_F(sys_call_test, fcntl_getfd) { TEST_F(sys_call_test, fcntl_getfd_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_open_t setup = [](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); @@ -191,9 +189,7 @@ TEST_F(sys_call_test, fcntl_getfd_dropping) { captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(0, callnum); } @@ -224,9 +220,7 @@ TEST_F(sys_call_test, bind_error_dropping) { captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(1, callnum); } @@ -277,9 +271,7 @@ TEST_F(sys_call_test, close_badfd_dropping) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(0, callnum); } @@ -1445,7 +1437,7 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { } }; - before_close_t cleanup = [&](sinsp* inspector) { + before_close_t before_close = [&](sinsp* inspector) { int result = 0; result += setresuid(orig_uids[0], orig_uids[1], orig_uids[2]); @@ -1456,8 +1448,9 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { } }; - ASSERT_NO_FATAL_FAILURE( - { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, callback, filter, event_capture::do_nothing, before_close); + }); EXPECT_EQ(8, callnum); } diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index 712d47773d..d238fca51a 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -279,7 +279,6 @@ void runtest(iotype iot, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, SINSP_MODE_LIVE, - 3, false); }); ASSERT_GT(callnum, 0); @@ -376,7 +375,6 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, SINSP_MODE_LIVE, - 3, false); }); ASSERT_EQ(1, state); diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index c8a9c3769a..60cf5ef09c 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -593,7 +593,6 @@ void runtest_ipv4m(iotype iot, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, SINSP_MODE_LIVE, - 3, false); }); } diff --git a/test/libsinsp_e2e/udp_client_server.cpp b/test/libsinsp_e2e/udp_client_server.cpp index 4ab4e7ef4d..b8671f6005 100644 --- a/test/libsinsp_e2e/udp_client_server.cpp +++ b/test/libsinsp_e2e/udp_client_server.cpp @@ -938,9 +938,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { n++; }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->dynamic_snaplen(false); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(4, n); } From 25e2d083cbc3a823c07ccfc3cebf437cbe331ec4 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 26 Sep 2024 12:46:38 +0200 Subject: [PATCH 04/20] chore(test/libsinsp/e2e): some renamings to improve readability. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 9 ++++---- test/libsinsp_e2e/event_capture.cpp | 12 +++++----- test/libsinsp_e2e/event_capture.h | 28 ++++++++++++++--------- test/libsinsp_e2e/fs.cpp | 4 ++-- test/libsinsp_e2e/suppress_events.cpp | 8 +++---- test/libsinsp_e2e/sys_call_test.cpp | 16 ++++++------- test/libsinsp_e2e/tcp_client_server.cpp | 2 +- test/libsinsp_e2e/udp_client_server.cpp | 6 ++--- 8 files changed, 45 insertions(+), 40 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index af674ad163..7b65c2e1c2 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -327,13 +327,12 @@ TEST_F(sys_call_test, container_docker_bad_socket) { return; } - before_open_t setup = [&](sinsp* inspector) { + before_capture_t setup = [&](sinsp* inspector) { inspector->set_docker_socket_path("/invalid/path"); }; event_filter_t filter = [&](sinsp_evt* evt) { if(evt->get_type() == PPME_CONTAINER_JSON_E || evt->get_type() == PPME_CONTAINER_JSON_2_E) { - printf("top container json\n"); return true; } auto tinfo = evt->get_thread_info(); @@ -590,7 +589,7 @@ static void healthcheck_helper( ASSERT_TRUE(dhelper.build_image() == 0); - before_open_t setup = [&](sinsp* inspector) { + before_capture_t setup = [&](sinsp* inspector) { // Setting dropping mode preserves the execs but // reduces the chances that we'll drop events during // the docker fetch. @@ -622,7 +621,7 @@ static void healthcheck_helper( } }; - before_close_t cleanup = [&](sinsp* inspector) { + after_capture_t cleanup = [&](sinsp* inspector) { capture_stats_str = capture_stats(inspector); }; @@ -808,7 +807,7 @@ TEST_F(sys_call_test, docker_container_large_json) { ASSERT_TRUE(dhelper.build_image() == 0); - before_open_t before = [&](sinsp* inspector) { + before_capture_t before = [&](sinsp* inspector) { inspector->set_container_labels_max_len(60000); }; diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 4f8f76a19d..4937512938 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -32,8 +32,8 @@ unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; event_capture::event_capture(sinsp_mode_t mode, captured_event_callback_t captured_event_callback, - before_open_t before_open, - before_close_t before_close, + before_capture_t before_open, + after_capture_t before_close, event_filter_t filter, uint32_t max_thread_table_size, uint64_t thread_timeout_ns, @@ -41,8 +41,8 @@ event_capture::event_capture(sinsp_mode_t mode, m_mode = mode; m_captured_event_callback = std::move(captured_event_callback); - m_before_open = std::move(before_open); - m_before_close = std::move(before_close); + m_before_capture = std::move(before_open); + m_after_capture = std::move(before_close); m_filter = std::move(filter); m_inspector = std::make_unique(); @@ -74,13 +74,13 @@ void event_capture::start(bool dump) { true); } - m_before_open(m_inspector.get()); + m_before_capture(m_inspector.get()); m_inspector->start_capture(); } void event_capture::stop() { m_inspector->stop_capture(); - m_before_close(m_inspector.get()); + m_after_capture(m_inspector.get()); if(m_dumper != nullptr) { m_dumper->close(); } diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index e936441710..deec15385a 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -22,7 +22,7 @@ limitations under the License. #include -#include +#include #include #include #include @@ -45,9 +45,15 @@ class callback_param { sinsp* m_inspector; }; -typedef std::function before_open_t; -typedef std::function before_close_t; +// Right before inspector->start_capture() gets called. +// Engine is already opened (thus scap handle is already alive). +typedef std::function before_capture_t; +// Right after inspector->stop_capture() gets called. +// Engine is still opened (thus scap handle is still alive). +typedef std::function after_capture_t; +// Only events matching the filter function are passed to the captured_event_callback_t. typedef std::function event_filter_t; +// On event callback typedef std::function captured_event_callback_t; typedef std::function run_callback_t; typedef std::function run_callback_async_t; @@ -56,8 +62,8 @@ class event_capture { public: event_capture(sinsp_mode_t mode, captured_event_callback_t captured_event_callback, - before_open_t before_open, - before_close_t before_close, + before_capture_t before_open, + after_capture_t before_close, event_filter_t filter, uint32_t max_thread_table_size, uint64_t thread_timeout_ns, @@ -72,8 +78,8 @@ class event_capture { static void run(const run_callback_t& run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, - before_open_t before_open = event_capture::do_nothing, - before_close_t before_close = event_capture::do_nothing, + before_capture_t before_open = event_capture::do_nothing, + after_capture_t before_close = event_capture::do_nothing, uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, @@ -102,8 +108,8 @@ class event_capture { static void run(const run_callback_async_t& run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, - before_open_t before_open = event_capture::do_nothing, - before_close_t before_close = event_capture::do_nothing, + before_capture_t before_open = event_capture::do_nothing, + after_capture_t before_close = event_capture::do_nothing, uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, @@ -150,8 +156,8 @@ class event_capture { std::unique_ptr m_dumper; event_filter_t m_filter; captured_event_callback_t m_captured_event_callback; - before_open_t m_before_open; - before_close_t m_before_close; + before_capture_t m_before_capture; + after_capture_t m_after_capture; callback_param m_param{}; sinsp_mode_t m_mode; }; diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index c460f8fb1f..a66c3f2951 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -1174,7 +1174,7 @@ TEST_F(sys_call_test, large_read_write) { srandom(42); - before_open_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; @@ -1267,7 +1267,7 @@ TEST_F(sys_call_test, large_readv_writev) { buf[j] = random(); } - before_open_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; diff --git a/test/libsinsp_e2e/suppress_events.cpp b/test/libsinsp_e2e/suppress_events.cpp index a922307748..611fc33179 100644 --- a/test/libsinsp_e2e/suppress_events.cpp +++ b/test/libsinsp_e2e/suppress_events.cpp @@ -37,7 +37,7 @@ static void test_helper_quotactl(test_helper_args& hargs) { // Access/modify inspector before opening // - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { inspector->clear_suppress_events_comm(); inspector->clear_suppress_events_tid(); @@ -103,7 +103,7 @@ static void test_helper_quotactl(test_helper_args& hargs) { } }; - before_close_t before_close = [](sinsp* inspector) { + after_capture_t before_close = [](sinsp* inspector) { scap_stats st; inspector->get_capture_stats(&st); @@ -243,7 +243,7 @@ void suppress_types::run_test(std::vector supp_syscalls) { parse_syscall_names(supp_syscalls, m_suppressed_syscalls); parse_suppressed_types(supp_syscalls, &m_suppressed_evttypes); - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { for(auto sc : m_suppressed_syscalls) { bool expect_exception = (sc >= PPM_SC_MAX); bool caught_exception = false; @@ -258,7 +258,7 @@ void suppress_types::run_test(std::vector supp_syscalls) { } }; - before_close_t before_close = [&](sinsp* inspector) { + after_capture_t before_close = [&](sinsp* inspector) { for(auto sc : m_suppressed_syscalls) { bool expect_exception = (sc >= PPM_SC_MAX); bool caught_exception = false; diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index 054cce6052..0389204747 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -135,7 +135,7 @@ TEST_F(sys_call_test, open_close) { TEST_F(sys_call_test, open_close_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return (0 == strcmp(evt->get_name(), "open") || 0 == strcmp(evt->get_name(), "openat") || @@ -179,7 +179,7 @@ TEST_F(sys_call_test, fcntl_getfd) { TEST_F(sys_call_test, fcntl_getfd_dropping) { int callnum = 0; - before_open_t setup = [](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); @@ -210,7 +210,7 @@ TEST_F(sys_call_test, bind_error) { TEST_F(sys_call_test, bind_error_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); @@ -251,7 +251,7 @@ TEST_F(sys_call_test, close_badfd) { TEST_F(sys_call_test, close_badfd_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); @@ -1008,7 +1008,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) { int callnum = 0; std::unique_ptr is_subprocess_execve; - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "evt.type=execve and proc.apid=" + std::to_string(getpid())); is_subprocess_execve = compiler.compile(); @@ -1437,7 +1437,7 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { } }; - before_close_t before_close = [&](sinsp* inspector) { + after_capture_t before_close = [&](sinsp* inspector) { int result = 0; result += setresuid(orig_uids[0], orig_uids[1], orig_uids[2]); @@ -1608,7 +1608,7 @@ TEST_F(sys_call_test32, failing_execve) { // INIT FILTER std::unique_ptr is_subprocess_execve; - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "evt.type=execve and proc.apid=" + std::to_string(getpid())); is_subprocess_execve.reset(compiler.compile().release()); @@ -2133,7 +2133,7 @@ TEST_F(sys_call_test, thread_lookup_live) { } }; - before_close_t before_close = [&](sinsp* inspector) { + after_capture_t before_close = [&](sinsp* inspector) { // close scap to maintain the num_consumers at exit == 0 assertion // close_capture(scap, platform); auto platform = (scap_linux_platform*)inspector->get_scap_platform(); diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index d238fca51a..683483d0ce 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -110,7 +110,7 @@ void runtest(iotype iot, // // INITIALIZATION // - before_open_t before = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; + before_capture_t before = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; run_callback_t test = [&](sinsp* inspector) { server_proc.start(); diff --git a/test/libsinsp_e2e/udp_client_server.cpp b/test/libsinsp_e2e/udp_client_server.cpp index b8671f6005..9c57ce0187 100644 --- a/test/libsinsp_e2e/udp_client_server.cpp +++ b/test/libsinsp_e2e/udp_client_server.cpp @@ -747,7 +747,7 @@ static void run_fd_name_changed_test(bool use_sendmsg, uint32_t num_name_changed_evts = 0; // INIT FILTER - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "fd.name_changed=true"); fd_name_changed = std::move(compiler.compile()); }; @@ -824,7 +824,7 @@ TEST_F(sys_call_test, udp_client_server_multiple_connect_name_changed) { uint32_t num_name_changed_evts = 0; // INIT FILTER - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "fd.name_changed=true"); fd_name_changed = std::move(compiler.compile()); }; @@ -891,7 +891,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { "ipsum:" "18|c"; - before_open_t setup = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; // // FILTER From 0a5a79ad0c1cfbf1167991fcf1b67f2556aa7cc9 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 26 Sep 2024 14:36:08 +0200 Subject: [PATCH 05/20] fix(test/libsinsp_e2e): use an `eventfd` to signal main thread that is time to leave. The `close` syscall might get lost leading to an infinite loop; instead, now we ask to the main thread to leave using thread safe eventfd, and the main thread will dequeue all remaining events until an error is returned by sinsp::next. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/event_capture.cpp | 62 +++++++++++++++---- test/libsinsp_e2e/event_capture.h | 24 ++++--- test/libsinsp_e2e/fs.cpp | 2 - test/libsinsp_e2e/suppress_events.cpp | 3 +- test/libsinsp_e2e/tcp_client_server.cpp | 2 - .../tcp_client_server_ipv4_mapped.cpp | 1 - 6 files changed, 63 insertions(+), 31 deletions(-) diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 4937512938..787f71fbc0 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -30,21 +30,21 @@ std::string event_capture::s_engine_string = KMOD_ENGINE; std::string event_capture::s_engine_path; unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; -event_capture::event_capture(sinsp_mode_t mode, - captured_event_callback_t captured_event_callback, +event_capture::event_capture(captured_event_callback_t captured_event_callback, before_capture_t before_open, after_capture_t before_close, event_filter_t filter, uint32_t max_thread_table_size, uint64_t thread_timeout_ns, uint64_t inactive_thread_scan_time_ns) { - m_mode = mode; - m_captured_event_callback = std::move(captured_event_callback); m_before_capture = std::move(before_open); m_after_capture = std::move(before_close); m_filter = std::move(filter); + m_eventfd = -1; + m_leaving = false; + m_inspector = std::make_unique(); m_inspector->m_thread_manager->set_max_thread_table_size(max_thread_table_size); m_inspector->m_thread_timeout_ns = thread_timeout_ns; @@ -58,6 +58,7 @@ event_capture::event_capture(sinsp_mode_t mode, } void event_capture::start(bool dump) { + m_eventfd = eventfd(0, EFD_NONBLOCK); open_engine(event_capture::get_engine(), {}); const ::testing::TestInfo* const test_info = @@ -79,6 +80,7 @@ void event_capture::start(bool dump) { } void event_capture::stop() { + close(m_eventfd); m_inspector->stop_capture(); m_after_capture(m_inspector.get()); if(m_dumper != nullptr) { @@ -92,7 +94,14 @@ void event_capture::capture() { bool result = true; int32_t next_result = SCAP_SUCCESS; + /* + * Loop until: + * * test has non fatal failures + * * handle_event returns true + * * we weren't asked to leave from eventfd and we received !SCAP_SUCCESS + */ while(result && !::testing::Test::HasFatalFailure()) { + handle_eventfd_request(); next_result = m_inspector->next(&event); if(next_result == SCAP_FILTERED_EVENT) { continue; @@ -102,6 +111,25 @@ void event_capture::capture() { m_dumper->dump(event); } result = handle_event(event); + } else if(m_leaving) { + break; + } + } + + /* + * Second loop to empty the buffers from all the generated events: + * * loop until SCAP_TIMEOUT is received. + */ + result = true; + while(result) { + next_result = m_inspector->next(&event); + if(next_result == SCAP_SUCCESS) { + if(m_dumper != nullptr) { + m_dumper->dump(event); + } + result = handle_event(event); + } else if(next_result == SCAP_TIMEOUT) { + break; } } } @@ -109,14 +137,8 @@ void event_capture::capture() { bool event_capture::handle_event(sinsp_evt* event) { bool res = true; - // Signal to exit! - if(event->get_type() == PPME_SYSCALL_CLOSE_E && - event->get_param(0)->as() == FD_SIGNAL_STOP) { - return false; - } - if(::testing::Test::HasNonfatalFailure()) { - return true; + return res; } if(m_filter(event)) { @@ -133,6 +155,24 @@ bool event_capture::handle_event(sinsp_evt* event) { return res; } +// Returns true if any request has been satisfied +bool event_capture::handle_eventfd_request() { + eventfd_t req; + int ret = eventfd_read(m_eventfd, &req); + if(ret == 0) { + // manage request + switch(req) { + case EVENTFD_SIGNAL_STOP: + m_inspector->stop_capture(); + m_leaving = true; + return true; + default: + break; + } + } + return false; +} + void event_capture::open_engine(const std::string& engine_string, libsinsp::events::set events_sc_codes) { if(false) { diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index deec15385a..0d244ca1b3 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -33,11 +33,12 @@ limitations under the License. #include #include #include +#include // Just a stupid fake FD value to signal to stop capturing events from driver and exit. // Note: we don't use it through eventfd because we want to make sure // that we received all events from the driver, until this very last close(FD_SIGNAL_STOP); -#define FD_SIGNAL_STOP 555 +#define EVENTFD_SIGNAL_STOP 1 class callback_param { public: @@ -60,8 +61,7 @@ typedef std::function run_callback_async_t; class event_capture { public: - event_capture(sinsp_mode_t mode, - captured_event_callback_t captured_event_callback, + event_capture(captured_event_callback_t captured_event_callback, before_capture_t before_open, after_capture_t before_close, event_filter_t filter, @@ -83,10 +83,8 @@ class event_capture { uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, - sinsp_mode_t mode = SINSP_MODE_LIVE, bool dump = true) { - event_capture capturing(mode, - std::move(captured_event_callback), + event_capture capturing(std::move(captured_event_callback), std::move(before_open), std::move(before_close), std::move(filter), @@ -98,7 +96,7 @@ class event_capture { run_function(capturing.m_inspector.get()); // signal main thread to end the capture - close(FD_SIGNAL_STOP); + eventfd_write(capturing.m_eventfd, EVENTFD_SIGNAL_STOP); capturing.capture(); @@ -113,10 +111,8 @@ class event_capture { uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, - sinsp_mode_t mode = SINSP_MODE_LIVE, bool dump = true) { - event_capture capturing(mode, - std::move(captured_event_callback), + event_capture capturing(std::move(captured_event_callback), std::move(before_open), std::move(before_close), std::move(filter), @@ -126,10 +122,10 @@ class event_capture { capturing.start(dump); - std::thread thread([&run_function]() { + std::thread thread([&run_function, &capturing]() { run_function(); // signal main thread to end the capture - close(FD_SIGNAL_STOP); + eventfd_write(capturing.m_eventfd, EVENTFD_SIGNAL_STOP); }); capturing.capture(); @@ -148,6 +144,7 @@ class event_capture { private: bool handle_event(sinsp_evt* event); + bool handle_eventfd_request(); void open_engine(const std::string& engine_string, libsinsp::events::set events_sc_codes); @@ -159,5 +156,6 @@ class event_capture { before_capture_t m_before_capture; after_capture_t m_after_capture; callback_param m_param{}; - sinsp_mode_t m_mode; + int m_eventfd; + bool m_leaving; }; diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index a66c3f2951..3b71b36fbb 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -1246,7 +1246,6 @@ TEST_F(sys_call_test, large_read_write) { 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, false); }); @@ -1365,7 +1364,6 @@ TEST_F(sys_call_test, large_readv_writev) { 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, false); }); diff --git a/test/libsinsp_e2e/suppress_events.cpp b/test/libsinsp_e2e/suppress_events.cpp index 611fc33179..2e8c176036 100644 --- a/test/libsinsp_e2e/suppress_events.cpp +++ b/test/libsinsp_e2e/suppress_events.cpp @@ -124,8 +124,7 @@ static void test_helper_quotactl(test_helper_args& hargs) { 131072, 6000, 6000, - SINSP_MODE_LIVE, - 1000); + true); }); } diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index 683483d0ce..b798befde0 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -278,7 +278,6 @@ void runtest(iotype iot, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, false); }); ASSERT_GT(callnum, 0); @@ -374,7 +373,6 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, false); }); ASSERT_EQ(1, state); diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index 60cf5ef09c..847cae5b92 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -592,7 +592,6 @@ void runtest_ipv4m(iotype iot, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, false); }); } From 999d876d2a3083754119a1527ca10cb404eaab1e Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Thu, 26 Sep 2024 17:02:06 +0200 Subject: [PATCH 06/20] fix(test/libsinsp_e2e): more fixes. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 43 +++++++++++++++---- test/libsinsp_e2e/forking.cpp | 25 +++++------ test/libsinsp_e2e/sys_call_test.cpp | 29 ++++++------- .../tcp_client_server_ipv4_mapped.cpp | 7 +-- 4 files changed, 61 insertions(+), 43 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 7b65c2e1c2..69ab550f38 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -590,10 +590,13 @@ static void healthcheck_helper( ASSERT_TRUE(dhelper.build_image() == 0); before_capture_t setup = [&](sinsp* inspector) { - // Setting dropping mode preserves the execs but - // reduces the chances that we'll drop events during - // the docker fetch. - inspector->start_dropping_mode(1); + // Set minimum event set to avoid drops + const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); + for(int i = 0; i < PPM_SC_MAX; i++) { + if(!state_sc_set.contains((ppm_sc_code)i)) { + inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); + } + } }; event_filter_t filter = [&](sinsp_evt* evt) { @@ -645,7 +648,17 @@ static void healthcheck_tracefile_helper( dockerfile + " . > /dev/null 2>&1"); ASSERT_TRUE(system(build_cmdline.c_str()) == 0); - run_callback_t test = [](sinsp* inspector) { + before_capture_t before = [&](sinsp* inspector) { + // Set minimum event set to avoid drops + const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); + for(int i = 0; i < PPM_SC_MAX; i++) { + if(!state_sc_set.contains((ppm_sc_code)i)) { + inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); + } + } + }; + + run_callback_async_t test = []() { // --network=none speeds up the container setup a bit. ASSERT_TRUE( (system("docker run --rm --network=none --name cont_health_ut cont_health_ut_img " @@ -659,7 +672,7 @@ static void healthcheck_tracefile_helper( captured_event_callback_t callback = [&](const callback_param& param) { return; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); // Now reread the file we just wrote and pass it through // update_container_state. @@ -809,6 +822,13 @@ TEST_F(sys_call_test, docker_container_large_json) { before_capture_t before = [&](sinsp* inspector) { inspector->set_container_labels_max_len(60000); + // Set minimum event set to avoid drops + const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); + for(int i = 0; i < PPM_SC_MAX; i++) { + if(!state_sc_set.contains((ppm_sc_code)i)) { + inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); + } + } }; event_filter_t filter = [&](sinsp_evt* evt) { @@ -816,7 +836,7 @@ TEST_F(sys_call_test, docker_container_large_json) { evt->get_type() == PPME_CONTAINER_JSON_2_E; }; - run_callback_t test = [&](sinsp* inspector) { + run_callback_async_t test = [&]() { int rc = dhelper.run_container("large_container_ut", "/bin/sh -c '/bin/sleep 3'"); ASSERT_TRUE(rc == 0); @@ -860,6 +880,11 @@ TEST_F(sys_call_test, docker_container_large_json) { param.m_inspector->set_container_labels_max_len(100); }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); - ASSERT_TRUE(saw_container_evt); + std::string capture_stats_str = "(Not Collected Yet)"; + after_capture_t cleanup = [&](sinsp* inspector) { + capture_stats_str = capture_stats(inspector); + }; + + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before, cleanup); }); + ASSERT_TRUE(saw_container_evt) << capture_stats_str; } diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 63442eb745..d0d03ec399 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -778,10 +778,6 @@ static int stop_sinsp_and_exit(void* arg) { return 1; } - sinsp* inspector = (sinsp*)arg; - - inspector->stop_capture(); - // Wait 5 seconds. This ensures that the state for this // process will be considered stale when the second process // with the same pid runs. @@ -874,7 +870,7 @@ static pid_t clone_helper(int (*func)(void*), TEST_F(sys_call_test, remove_stale_thread_clone_exit) { uint32_t clones_seen = 0; stale_clone_ctx ctx; - std::atomic recycle_pid(0); + pid_t recycle_pid; const char* last_pid_filename = "/proc/sys/kernel/ns_last_pid"; struct stat info; @@ -897,8 +893,7 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // uses the recycled pid. event_filter_t filter = [&](sinsp_evt* evt) { sinsp_threadinfo* tinfo = evt->get_thread_info(); - pid_t rp = recycle_pid.load(); - return (rp != 0 && tinfo && tinfo->m_tid == rp); + return (tinfo && tinfo->m_tid == recycle_pid); }; run_callback_t test = [&](sinsp* inspector) { @@ -915,13 +910,15 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // This is asynchronous so wait to make sure the thread has started. sleep(1); - // Start a thread that runs and stops the inspector_handle right - // before exiting. This gives us a pid we can use for the - // second thread. - recycle_pid.store(clone_helper(stop_sinsp_and_exit, nullptr)); - ASSERT_GE(recycle_pid.load(), 0); + // Start a thread that runs, chdir to /dev/ and the exits. + // This gives us a pid we can use for the second thread. + // We don't want to capture events from this CLONE. + inspector->stop_capture(); + + recycle_pid = clone_helper(stop_sinsp_and_exit, inspector); + ASSERT_GE(recycle_pid, 0); - // The first thread has started, turned off the capturing, and + // The first thread has started, chdir to /dev, and // exited, so start capturing again. inspector->start_capture(); @@ -946,7 +943,7 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { ASSERT_EQ(flock(fileno(last_pid_file), LOCK_EX), 0); - ASSERT_GT(fprintf(last_pid_file, "%d", recycle_pid.load() - 1), 0); + ASSERT_GT(fprintf(last_pid_file, "%d", recycle_pid - 1), 0); fclose(last_pid_file); diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index 0389204747..6208205c39 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -1712,7 +1712,7 @@ TEST_F(sys_call_test32, mmap) { return tinfo && tinfo->m_comm == "test_helper_32" && ps_filter(evt); }; - uint64_t p = 0; + uint64_t p = -1; // // TEST CODE @@ -1728,10 +1728,8 @@ TEST_F(sys_call_test32, mmap) { errno2 = std::stoi(tmp.str()); tmp.clear(); tmp.str(""); - tmp << handle.out(); - p = (uint64_t)std::stoul(tmp.str()); - tmp.clear(); - tmp.str(""); + tmp << std::hex << handle.out(); + tmp >> p; handle.wait(); }; @@ -1759,8 +1757,7 @@ TEST_F(sys_call_test32, mmap) { EXPECT_EQ("300", e->get_param_value_str("length")); break; case 7: { - uint64_t addr = 0; - memcpy(&addr, e->get_param_by_name("addr")->m_val, sizeof(uint64_t)); + auto addr = e->get_param_by_name("addr")->as(); #ifdef __LP64__ EXPECT_EQ((uint64_t)p, addr); #else @@ -1775,8 +1772,8 @@ TEST_F(sys_call_test32, mmap) { } else if(type == PPME_SYSCALL_MUNMAP_X) { callnum++; - memcpy(&exit_vmsize, e->get_param_by_name("vm_size")->m_val, sizeof(uint32_t)); - memcpy(&exit_vmrss, e->get_param_by_name("vm_rss")->m_val, sizeof(uint32_t)); + exit_vmsize = e->get_param_by_name("vm_size")->as(); + exit_vmrss = e->get_param_by_name("vm_rss")->as(); EXPECT_EQ(e->get_thread_info(false)->m_vmsize_kb, exit_vmsize); EXPECT_EQ(e->get_thread_info(false)->m_vmrss_kb, exit_vmrss); @@ -1833,22 +1830,20 @@ TEST_F(sys_call_test32, mmap) { } else if(type == PPME_SYSCALL_MMAP_X || type == PPME_SYSCALL_MMAP2_X) { callnum++; - memcpy(&exit_vmsize, e->get_param_by_name("vm_size")->m_val, sizeof(uint32_t)); - memcpy(&exit_vmrss, e->get_param_by_name("vm_rss")->m_val, sizeof(uint32_t)); + exit_vmsize = e->get_param_by_name("vm_size")->as(); + exit_vmrss = e->get_param_by_name("vm_rss")->as(); EXPECT_EQ(e->get_thread_info(false)->m_vmsize_kb, exit_vmsize); EXPECT_EQ(e->get_thread_info(false)->m_vmrss_kb, exit_vmrss); switch(callnum) { case 4: { - uint64_t res = 0; - memcpy(&res, e->get_param_by_name("res")->m_val, sizeof(uint64_t)); - EXPECT_EQ(-errno2, (int64_t)res); + auto res = e->get_param_by_name("res")->as(); + EXPECT_EQ(-errno2, res); break; } case 6: { - uint64_t res = 0; - memcpy(&res, e->get_param_by_name("res")->m_val, sizeof(uint64_t)); - EXPECT_EQ((uint64_t)p, res); + auto res = e->get_param_by_name("res")->as(); + EXPECT_EQ(p, res); EXPECT_GT(exit_vmsize, enter_vmsize + 500); EXPECT_GE(exit_vmrss, enter_vmrss); break; diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index 847cae5b92..b87c96be65 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -374,7 +374,7 @@ void runtest_ipv4m(iotype iot, std::string sport; int state = 0; int ctid; - int tid = getpid(); + int tid = -1; // // FILTER @@ -386,7 +386,8 @@ void runtest_ipv4m(iotype iot, // // INITIALIZATION // - run_callback_t test = [&](sinsp* inspector) { + run_callback_async_t test = [&]() { + tid = gettid(); server_thread = std::thread(&tcp_server_ipv4m::run, server); server->wait_till_ready(); @@ -555,7 +556,7 @@ void runtest_ipv4m(iotype iot, } else if(evt->get_type() == PPME_SYSCALL_READV_X) { std::string ds = evt->get_param_value_str("data"); - EXPECT_EQ(ds, evt->get_param_value_str("data")); + EXPECT_EQ(PAYLOAD, evt->get_param_value_str("data")); log_param(param); callnum++; From fb293fc286ea264eaee1df9a73c3156cbe9eb077 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 09:15:34 +0200 Subject: [PATCH 07/20] fix(userspace/libsinsp, test/libsinsp_e2e): fixed libvirt-lxc container resolving on newer linux systemd systems. This fixes the `sys_call_test.container_libvirt` running on my machine. Also, let event_capture always print capture stats for us. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 64 ++++++++----------- test/libsinsp_e2e/event_capture.cpp | 17 ++++- test/libsinsp_e2e/event_capture.h | 3 + .../libsinsp/container_engine/libvirt_lxc.cpp | 13 +++- 4 files changed, 54 insertions(+), 43 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 69ab550f38..22e726f777 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -391,6 +391,16 @@ TEST_F(sys_call_test, container_libvirt) { return; } + before_capture_t setup = [&](sinsp* inspector) { + // Set minimum event set to avoid drops + const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); + for(int i = 0; i < PPM_SC_MAX; i++) { + if(!state_sc_set.contains((ppm_sc_code)i)) { + inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); + } + } + }; + event_filter_t filter = [&](sinsp_evt* evt) { sinsp_threadinfo* tinfo = evt->get_thread_info(); if(tinfo) { @@ -400,7 +410,7 @@ TEST_F(sys_call_test, container_libvirt) { return false; }; - run_callback_async_t test = [&]() { + run_callback_async_t test = []() { FILE* f = fopen("/tmp/conf.xml", "w"); ASSERT_TRUE(f != NULL); fprintf(f, @@ -459,7 +469,7 @@ TEST_F(sys_call_test, container_libvirt) { done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); ASSERT_TRUE(done); } @@ -478,18 +488,6 @@ class container_state { bool healthcheck_seen; }; -static std::string capture_stats(sinsp* inspector) { - scap_stats st; - inspector->get_capture_stats(&st); - - std::stringstream ss; - - ss << "capture stats: dropped=" << st.n_drops << " buf=" << st.n_drops_buffer - << " pf=" << st.n_drops_pf << " bug=" << st.n_drops_bug; - - return ss.str(); -} - static void update_container_state(sinsp* inspector, sinsp_evt* evt, container_state& cstate, @@ -520,8 +518,7 @@ static void update_container_state(sinsp* inspector, if(!cstate.root_cmd_seen) { cstate.root_cmd_seen = true; - ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER) - << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER); } else { // In some cases, it can take so long for the async fetch of container info to // complete (1.5 seconds) that a healthcheck proc might be run before the container @@ -529,7 +526,7 @@ static void update_container_state(sinsp* inspector, // the container info has a health probe. if(cstate.container_w_health_probe) { cstate.healthcheck_seen = true; - ASSERT_EQ(tinfo->m_category, expected_cat) << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, expected_cat); } } } @@ -539,13 +536,12 @@ static void update_container_state(sinsp* inspector, if(cmdline == "sleep 10") { if(!cstate.second_cmd_seen) { cstate.second_cmd_seen = true; - ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER) - << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER); } else { // See above caveat about slow container info fetches if(cstate.container_w_health_probe) { // Should inherit container healthcheck property from parent. - ASSERT_EQ(tinfo->m_category, expected_cat) << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, expected_cat); } } } @@ -555,7 +551,7 @@ static void update_container_state(sinsp* inspector, if(cmdline == "ut-health-check" || cmdline == "sh -c /bin/ut-health-check") { cstate.healthcheck_seen = true; - ASSERT_EQ(tinfo->m_category, expected_cat) << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, expected_cat); } } } @@ -572,7 +568,6 @@ static void healthcheck_helper( sinsp_threadinfo::command_category expected_cat = sinsp_threadinfo::CAT_HEALTHCHECK) { container_state cstate; bool exited_early = false; - std::string capture_stats_str = "(Not Collected Yet)"; if(!dutils_check_docker()) { return; @@ -624,16 +619,12 @@ static void healthcheck_helper( } }; - after_capture_t cleanup = [&](sinsp* inspector) { - capture_stats_str = capture_stats(inspector); - }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); - ASSERT_TRUE(cstate.root_cmd_seen) << capture_stats_str; - ASSERT_TRUE(cstate.second_cmd_seen) << capture_stats_str; - ASSERT_EQ(cstate.container_w_health_probe, expect_healthcheck) << capture_stats_str; - ASSERT_EQ(cstate.healthcheck_seen, expect_healthcheck) << capture_stats_str; + ASSERT_TRUE(cstate.root_cmd_seen); + ASSERT_TRUE(cstate.second_cmd_seen); + ASSERT_EQ(cstate.container_w_health_probe, expect_healthcheck); + ASSERT_EQ(cstate.healthcheck_seen, expect_healthcheck); } static void healthcheck_tracefile_helper( @@ -705,7 +696,7 @@ static void healthcheck_tracefile_helper( update_container_state(&inspector, ev, cstate, expected_cat); } - std::string capture_stats_str = capture_stats(&inspector); + std::string capture_stats_str = event_capture::capture_stats(&inspector); inspector.stop_capture(); inspector.close(); @@ -880,11 +871,6 @@ TEST_F(sys_call_test, docker_container_large_json) { param.m_inspector->set_container_labels_max_len(100); }; - std::string capture_stats_str = "(Not Collected Yet)"; - after_capture_t cleanup = [&](sinsp* inspector) { - capture_stats_str = capture_stats(inspector); - }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before, cleanup); }); - ASSERT_TRUE(saw_container_evt) << capture_stats_str; + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); + ASSERT_TRUE(saw_container_evt); } diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 787f71fbc0..46481d080b 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -132,6 +132,9 @@ void event_capture::capture() { break; } } + + auto capture_stats_str = capture_stats(m_inspector.get()); + std::cout << capture_stats_str << "\n"; } bool event_capture::handle_event(sinsp_evt* event) { @@ -173,6 +176,18 @@ bool event_capture::handle_eventfd_request() { return false; } +std::string event_capture::capture_stats(sinsp* inspector) { + scap_stats st; + inspector->get_capture_stats(&st); + + std::stringstream ss; + + ss << "capture stats: dropped=" << st.n_drops << " buf=" << st.n_drops_buffer + << " pf=" << st.n_drops_pf << " bug=" << st.n_drops_bug; + + return ss.str(); +} + void event_capture::open_engine(const std::string& engine_string, libsinsp::events::set events_sc_codes) { if(false) { @@ -186,7 +201,7 @@ void event_capture::open_engine(const std::string& engine_string, else if(!engine_string.compare(BPF_ENGINE)) { if(event_capture::get_engine().empty()) { std::cerr << "You must specify the path to the bpf probe if you use the 'bpf' engine" - << std::endl; + << '\n'; exit(EXIT_FAILURE); } m_inspector->open_bpf(event_capture::get_engine_path(), s_buffer_dim); diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index 0d244ca1b3..ae71d5cc05 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -138,6 +138,9 @@ class event_capture { static const std::string& get_engine(); static void set_buffer_dim(const unsigned long& dim); static const std::string& get_engine_path(); + + static std::string capture_stats(sinsp* inspector); + static std::string s_engine_string; static std::string s_engine_path; static unsigned long s_buffer_dim; diff --git a/userspace/libsinsp/container_engine/libvirt_lxc.cpp b/userspace/libsinsp/container_engine/libvirt_lxc.cpp index 161c87f377..676aa2985c 100644 --- a/userspace/libsinsp/container_engine/libvirt_lxc.cpp +++ b/userspace/libsinsp/container_engine/libvirt_lxc.cpp @@ -38,12 +38,19 @@ bool libvirt_lxc::match(sinsp_threadinfo* tinfo, sinsp_container_info& container } // - // systemd libvirt-lxc + // systemd libvirt-lxc: // pos = cgroup.find("-lxc\\x2"); if(pos != std::string::npos) { - size_t pos2 = cgroup.find(".scope"); - if(pos2 != std::string::npos && pos2 == cgroup.length() - sizeof(".scope") + 1) { + std::string delimiter = ".scope"; + size_t pos2 = cgroup.find(delimiter); + // For cgroups like: + // /machine.slice/machine-lxc\x2d2293906\x2dlibvirt\x2dcontainer.scope/libvirt, + // account for /libvirt below. + if(cgroup.find(".scope/libvirt") != std::string::npos) { + delimiter = ".scope/libvirt"; + } + if(pos2 != std::string::npos && pos2 == cgroup.length() - delimiter.length()) { container_info.m_type = CT_LIBVIRT_LXC; container_info.m_id = cgroup.substr(pos + sizeof("-lxc\\x2"), pos2 - pos - sizeof("-lxc\\x2")); From 016839ce42cd2b1c48dd8c44ada38c19a54d3f30 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 09:55:18 +0200 Subject: [PATCH 08/20] chore(test/libsinsp_e2e): use an atomic for `healthcheck_helper::exited_early`. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 22e726f777..84050ea55b 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -567,7 +567,7 @@ static void healthcheck_helper( std::vector& labels, sinsp_threadinfo::command_category expected_cat = sinsp_threadinfo::CAT_HEALTHCHECK) { container_state cstate; - bool exited_early = false; + std::atomic exited_early = false; if(!dutils_check_docker()) { return; @@ -829,7 +829,6 @@ TEST_F(sys_call_test, docker_container_large_json) { run_callback_async_t test = [&]() { int rc = dhelper.run_container("large_container_ut", "/bin/sh -c '/bin/sleep 3'"); - ASSERT_TRUE(rc == 0); }; From d2a9338b72984f0fa853d88355a6853786610da1 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 11:28:05 +0200 Subject: [PATCH 09/20] chore(test/libsinsp_e2e): disable `get_procs_cpu_from_driver`. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/event_capture.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 46481d080b..8729a4f59b 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -50,9 +50,9 @@ event_capture::event_capture(captured_event_callback_t captured_event_callback, m_inspector->m_thread_timeout_ns = thread_timeout_ns; m_inspector->set_auto_threads_purging_interval_s(inactive_thread_scan_time_ns); m_inspector->set_auto_threads_purging(false); - m_inspector->set_get_procs_cpu_from_driver(true); m_inspector->set_debug_mode(true); m_inspector->set_hostname_and_port_resolution_mode(false); + libsinsp_logger()->add_stdout_log(); m_param.m_inspector = m_inspector.get(); } From 8c2e098647eb1f1ee75e681c2520053fc5de1139 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 12:11:19 +0200 Subject: [PATCH 10/20] chore(test,userspace): properly reset docker_socket in tests since it is a static. Rename `m_docker_sock` to `s_docker_sock` to highlight that it is static. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 6 +++++- userspace/libsinsp/container_engine/docker/docker_linux.cpp | 6 +++--- userspace/libsinsp/container_engine/docker/docker_linux.h | 4 ++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 84050ea55b..fa9604314f 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -379,7 +379,11 @@ TEST_F(sys_call_test, container_docker_bad_socket) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); + after_capture_t cleanup = [&](sinsp* inspector) { + inspector->set_docker_socket_path("/var/run/docker.sock"); + }; + + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); ASSERT_TRUE(done); } diff --git a/userspace/libsinsp/container_engine/docker/docker_linux.cpp b/userspace/libsinsp/container_engine/docker/docker_linux.cpp index a6d75cb1c3..34e2f8ba1d 100644 --- a/userspace/libsinsp/container_engine/docker/docker_linux.cpp +++ b/userspace/libsinsp/container_engine/docker/docker_linux.cpp @@ -30,7 +30,7 @@ constexpr const cgroup_layout DOCKER_CGROUP_LAYOUT[] = {{"/", ""}, // non-syste {nullptr, nullptr}}; } -std::string docker_linux::m_docker_sock = "/var/run/docker.sock"; +std::string docker_linux::s_docker_sock = "/var/run/docker.sock"; bool docker_linux::resolve(sinsp_threadinfo* tinfo, bool query_os_for_missing_info) { std::string container_id, cgroup; @@ -40,7 +40,7 @@ bool docker_linux::resolve(sinsp_threadinfo* tinfo, bool query_os_for_missing_in } return resolve_impl(tinfo, - docker_lookup_request(container_id, m_docker_sock, CT_DOCKER, 0, false), + docker_lookup_request(container_id, s_docker_sock, CT_DOCKER, 0, false), query_os_for_missing_info); } @@ -61,7 +61,7 @@ void docker_linux::update_with_size(const std::string& container_id) { sinsp_container_info result; docker_lookup_request instruction(container_id, - m_docker_sock, + s_docker_sock, CT_DOCKER, 0, true /*request rw size*/); diff --git a/userspace/libsinsp/container_engine/docker/docker_linux.h b/userspace/libsinsp/container_engine/docker/docker_linux.h index a7c15d610e..393f488db5 100644 --- a/userspace/libsinsp/container_engine/docker/docker_linux.h +++ b/userspace/libsinsp/container_engine/docker/docker_linux.h @@ -10,7 +10,7 @@ class docker_linux : public docker_base { public: docker_linux(container_cache_interface& cache): docker_base(cache) {} - static void set_docker_sock(std::string docker_sock) { m_docker_sock = std::move(docker_sock); } + static void set_docker_sock(std::string docker_sock) { s_docker_sock = std::move(docker_sock); } // implement container_engine_base bool resolve(sinsp_threadinfo* tinfo, bool query_os_for_missing_info) override; @@ -18,7 +18,7 @@ class docker_linux : public docker_base { void update_with_size(const std::string& container_id) override; private: - static std::string m_docker_sock; + static std::string s_docker_sock; }; } // namespace container_engine From 31378fcd8540bd9dc64884694450e42cdd97d145 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 13:16:47 +0200 Subject: [PATCH 11/20] fix(driver/modern_bpf): fixed cgroup paths management for path_components > MAX_CGROUP_PATH_POINTERS Signed-off-by: Federico Di Pierro --- .../helpers/store/auxmap_store_params.h | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/driver/modern_bpf/helpers/store/auxmap_store_params.h b/driver/modern_bpf/helpers/store/auxmap_store_params.h index 5887b63d04..b9016f3006 100644 --- a/driver/modern_bpf/helpers/store/auxmap_store_params.h +++ b/driver/modern_bpf/helpers/store/auxmap_store_params.h @@ -1303,7 +1303,7 @@ static __always_inline uint16_t store_cgroup_subsys(struct auxiliary_map *auxmap * at the end of the string, reading with `bpf_probe_read_str()`). * * The rationale here is to replace the string terminator '\0' - * with the '/' for every path compotent, excluding the last. + * with the '/' for every path component, excluding the last. * * Starting from what we have already inserted ("cpuset="), * we want to obtain as a final result: @@ -1323,6 +1323,39 @@ static __always_inline uint16_t store_cgroup_subsys(struct auxiliary_map *auxmap * * cpuset=/path_part1/path_part2\0 */ + + /* + * If kernfs node is still not NULL, it means last path component retrieved + * (ie: the first one to be printed) was still not '\0' (ie: '/'). + * To avoid sending a cgroup that does not start with '/', manually add it. + * + * Example: + * /user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-2f17b2eb-994e-415d-bce0-44c1447d7cd2.scope + * gets split as: + * * vte-spawn-2f17b2eb-994e-415d-bce0-44c1447d7cd2.scope\0 + * * app-org.gnome.Terminal.slice\0 + * * app.slice\0 + * * user@1000.service\0 + * * user-1000.slice\0 + * * user.slice\0 + * Without the below fix, we would send to userspace "user.slice/user-1000.slice/..." without + * leading '/'. + * + * Counter example with "5" components + the root: + * /user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice + * gets split as: + * * app-org.gnome.Terminal.slice\0 + * * app.slice\0 + * * user@1000.service\0 + * * user-1000.slice\0 + * * user.slice\0 + * * \0 + * In this case, we won't push the new character, instead we will push the correct string. + */ + if(kn) { + push__new_character(auxmap->data, &auxmap->payload_pos, '/'); + total_size++; + } for(int k = MAX_CGROUP_PATH_POINTERS - 1; k >= 0; --k) { if(cgroup_path_pointers[k]) { total_size += push__charbuf(auxmap->data, From fdb1daaa98593be7f7fe47c7d9da10c64a5a66a3 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 13:34:11 +0200 Subject: [PATCH 12/20] chore(test/libsinsp_e2e): try harder to avoid issues in `tcp_client_server_with_connection_before_capturing_starts_ipv4m` test. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index b87c96be65..63ab2e6413 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -662,8 +662,8 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts_ }; server_thread = std::thread(&tcp_server_ipv4m::run, &server); - client_thread = std::thread(&tcp_client_ipv4m::run, &client); server.wait_till_ready(); + client_thread = std::thread(&tcp_client_ipv4m::run, &client); client.wait_till_ready(); ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); From b6dc25a39b269a69d6cfb4644efedff1ce86b00d Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 14:31:38 +0200 Subject: [PATCH 13/20] fix(test/libsinsp_e2e): only enable generic syscalls in `timestamp` test to avoid drops. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/sys_call_test.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index 6208205c39..3ea8722075 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -507,6 +507,17 @@ TEST_F(sys_call_test, timestamp) { uint64_t timestampv[20]; int callnum = 0; + before_capture_t setup = [&](sinsp* inspector) { + // Drop all but generic syscalls (since PPM_SC_GETTIMEOFDAY is generic) + // to avoid drops. + const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); + for(int i = 0; i < PPM_SC_MAX; i++) { + if((ppm_sc_code)i != PPM_SC_GETTIMEOFDAY) { + inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); + } + } + }; + event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; run_callback_t test = [&](sinsp* inspector) { @@ -529,7 +540,7 @@ TEST_F(sys_call_test, timestamp) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ((int)(sizeof(timestampv) / sizeof(timestampv[0])), callnum); } From 5b148002ad7ff29e44685fd3f4cd935d2cb63e2a Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 27 Sep 2024 14:51:56 +0200 Subject: [PATCH 14/20] chore(test/libsinsp_e2e): avoid using useless atomics. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/forking.cpp | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index d0d03ec399..ec3b3c672e 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -201,8 +201,8 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { } TEST_F(sys_call_test, forking_process_expired) { - std::atomic ptid = -1; // parent tid - std::atomic ctid = -1; // child tid + int ptid = gettid(); // parent tid + int ctid = -1; // child tid int status; // @@ -211,7 +211,7 @@ TEST_F(sys_call_test, forking_process_expired) { event_filter_t filter = [&](sinsp_evt* evt) { if(evt->get_type() == PPME_SYSCALL_NANOSLEEP_E || evt->get_type() == PPME_SYSCALL_NANOSLEEP_X) { - return evt->get_tid() == ptid.load(); + return evt->get_tid() == ptid; } return false; }; @@ -230,8 +230,6 @@ TEST_F(sys_call_test, forking_process_expired) { FAIL(); } else // fork() returns new pid to the parent process { - ptid = gettid(); - // // Wait 10 seconds. During this time, the process should NOT be removed // @@ -260,15 +258,13 @@ TEST_F(sys_call_test, forking_process_expired) { // // The child should exist // - sinsp_threadinfo* ti = - param.m_inspector->get_thread_ref(ctid.load(), false, true).get(); + sinsp_threadinfo* ti = param.m_inspector->get_thread_ref(ctid, false, true).get(); EXPECT_NE((sinsp_threadinfo*)NULL, ti); } else if(e->get_type() == PPME_SYSCALL_NANOSLEEP_X) { // // The child should exist // - sinsp_threadinfo* ti = - param.m_inspector->get_thread_ref(ctid.load(), false, true).get(); + sinsp_threadinfo* ti = param.m_inspector->get_thread_ref(ctid, false, true).get(); EXPECT_NE((sinsp_threadinfo*)NULL, ti); sleep_caught = true; } @@ -314,7 +310,7 @@ static int clone_callback_1(void* arg) { } /* - * The `sys_call_test.forking_clone_fs` e2e test makes the assuption + * The `sys_call_test.forking_clone_fs` e2e test makes the assumption * that, if a children closes a file descriptor, the parent trying * to close the same file descriptor will get an error. This seems * not to be always the case. As the man says `It is probably unwise @@ -328,7 +324,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { int callnum = 0; char bcwd[1024]; int prfd; - std::atomic ptid; // parent tid + int ptid = gettid(); // parent tid pid_t clone_tid; int child_tid; int parent_res; @@ -340,7 +336,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { // FILTER // event_filter_t filter = [&](sinsp_evt* evt) { - return evt->get_tid() == ptid.load() || evt->get_tid() == child_tid; + return evt->get_tid() == ptid || evt->get_tid() == child_tid; }; // @@ -354,8 +350,6 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { int status; pid_t pid; - ptid = gettid(); - /* Set up an argument structure to be passed to cloned child, and set some process attributes that will be modified by child */ @@ -467,7 +461,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { int callnum = 0; char bcwd[1024]; int prfd; - std::atomic ptid = -1; // parent tid + int ptid = gettid(); // parent tid int flags = CLONE_FS | CLONE_VM; int drflags = PPM_CL_CLONE_FS | PPM_CL_CLONE_VM; @@ -475,7 +469,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { // FILTER // event_filter_t filter = [&](sinsp_evt* evt) { - return evt->get_tid() == ptid.load() || evt->get_tid() == ctid; + return evt->get_tid() == ptid || evt->get_tid() == ctid; }; // @@ -489,8 +483,6 @@ TEST_F(sys_call_test, forking_clone_nofs) { int status; pid_t pid; - ptid = gettid(); - /* Set up an argument structure to be passed to cloned child, and set some process attributes that will be modified by child */ @@ -605,7 +597,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { int callnum = 0; char oriwd[1024]; char bcwd[256]; - std::atomic ptid = -1; // parent tid + int ptid = gettid(); // parent tid int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD; int drflags = PPM_CL_CLONE_VM | PPM_CL_CLONE_FS | PPM_CL_CLONE_FILES | PPM_CL_CLONE_SIGHAND | PPM_CL_CLONE_THREAD; @@ -613,7 +605,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { // // FILTER // - event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ptid.load(); }; + event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ptid; }; // // TEST CODE @@ -623,8 +615,6 @@ TEST_F(sys_call_test, forking_clone_cwd) { char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ - ptid = gettid(); - ASSERT_TRUE(getcwd(oriwd, 1024) != NULL); /* Allocate stack for child */ From 93776c42bb5497c90a60f96edbcfa60b009f1815 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 30 Sep 2024 10:22:30 +0200 Subject: [PATCH 15/20] fix(test): try harder to avoid event loss. Default interesting syscalls set now avoids `read` and `pread` to avoid back-pressure with `eventfd_read` being called at each loop iteration. Moreover, `event_capture::run()` now accepts a ppm_sc_set parameter to customize the sc set for the test. Finally, in rlimit related tests, reset old limits upon leaving. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 144 ++++++++++-------- test/libsinsp_e2e/event_capture.cpp | 24 ++- test/libsinsp_e2e/event_capture.h | 26 +++- test/libsinsp_e2e/forking.cpp | 10 +- test/libsinsp_e2e/fs.cpp | 11 +- test/libsinsp_e2e/process.cpp | 81 ++++++---- test/libsinsp_e2e/suppress_events.cpp | 1 + test/libsinsp_e2e/sys_call_test.cpp | 9 +- test/libsinsp_e2e/tcp_client_server.cpp | 2 + .../tcp_client_server_ipv4_mapped.cpp | 25 +-- 10 files changed, 207 insertions(+), 126 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index fa9604314f..02121f1e2c 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -107,7 +107,14 @@ TEST_F(sys_call_test, container_cgroups) { done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -172,7 +179,14 @@ TEST_F(sys_call_test, container_clone_nspid) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -216,7 +230,14 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); free(stack); ASSERT_TRUE(done); } @@ -289,7 +310,14 @@ static void run_container_docker_test(bool fork_after_container_start) { done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -395,26 +423,8 @@ TEST_F(sys_call_test, container_libvirt) { return; } - before_capture_t setup = [&](sinsp* inspector) { - // Set minimum event set to avoid drops - const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); - for(int i = 0; i < PPM_SC_MAX; i++) { - if(!state_sc_set.contains((ppm_sc_code)i)) { - inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); - } - } - }; - - event_filter_t filter = [&](sinsp_evt* evt) { - sinsp_threadinfo* tinfo = evt->get_thread_info(); - if(tinfo) { - return !tinfo->m_container_id.empty() && tinfo->m_comm == "sh"; - } - - return false; - }; - - run_callback_async_t test = []() { + // Setup phase before capture has start, to avoid generating too many events + before_capture_t setup = [](sinsp* inspector) { FILE* f = fopen("/tmp/conf.xml", "w"); ASSERT_TRUE(f != NULL); fprintf(f, @@ -440,15 +450,21 @@ TEST_F(sys_call_test, container_libvirt) { if(system("virsh -c lxc:/// define /tmp/conf.xml") != 0) { ASSERT_TRUE(false); } + }; + + event_filter_t filter = [&](sinsp_evt* evt) { + sinsp_threadinfo* tinfo = evt->get_thread_info(); + if(tinfo) { + return !tinfo->m_container_id.empty() && tinfo->m_comm == "sh"; + } + return false; + }; + run_callback_async_t test = []() { if(system("virsh -c lxc:/// start libvirt-container") != 0) { ASSERT_TRUE(false); } - sleep(2); - - ASSERT_TRUE(system("virsh -c lxc:/// undefine libvirt-container > /dev/null 2>&1") == 0); - ASSERT_TRUE(system("virsh -c lxc:/// destroy libvirt-container > /dev/null 2>&1") == 0); }; captured_event_callback_t callback = [&](const callback_param& param) { @@ -473,7 +489,19 @@ TEST_F(sys_call_test, container_libvirt) { done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); + after_capture_t cleanup = [](sinsp* inspector) { + ASSERT_TRUE(system("virsh -c lxc:/// undefine libvirt-container > /dev/null 2>&1") == 0); + ASSERT_TRUE(system("virsh -c lxc:/// destroy libvirt-container > /dev/null 2>&1") == 0); + }; + + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + setup, + cleanup, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -588,16 +616,6 @@ static void healthcheck_helper( ASSERT_TRUE(dhelper.build_image() == 0); - before_capture_t setup = [&](sinsp* inspector) { - // Set minimum event set to avoid drops - const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); - for(int i = 0; i < PPM_SC_MAX; i++) { - if(!state_sc_set.contains((ppm_sc_code)i)) { - inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); - } - } - }; - event_filter_t filter = [&](sinsp_evt* evt) { sinsp_threadinfo* tinfo = evt->get_thread_info(); @@ -623,7 +641,14 @@ static void healthcheck_helper( } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(cstate.root_cmd_seen); ASSERT_TRUE(cstate.second_cmd_seen); @@ -643,16 +668,6 @@ static void healthcheck_tracefile_helper( dockerfile + " . > /dev/null 2>&1"); ASSERT_TRUE(system(build_cmdline.c_str()) == 0); - before_capture_t before = [&](sinsp* inspector) { - // Set minimum event set to avoid drops - const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); - for(int i = 0; i < PPM_SC_MAX; i++) { - if(!state_sc_set.contains((ppm_sc_code)i)) { - inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); - } - } - }; - run_callback_async_t test = []() { // --network=none speeds up the container setup a bit. ASSERT_TRUE( @@ -667,7 +682,14 @@ static void healthcheck_tracefile_helper( captured_event_callback_t callback = [&](const callback_param& param) { return; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); // Now reread the file we just wrote and pass it through // update_container_state. @@ -817,13 +839,6 @@ TEST_F(sys_call_test, docker_container_large_json) { before_capture_t before = [&](sinsp* inspector) { inspector->set_container_labels_max_len(60000); - // Set minimum event set to avoid drops - const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); - for(int i = 0; i < PPM_SC_MAX; i++) { - if(!state_sc_set.contains((ppm_sc_code)i)) { - inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); - } - } }; event_filter_t filter = [&](sinsp_evt* evt) { @@ -869,11 +884,20 @@ TEST_F(sys_call_test, docker_container_large_json) { } EXPECT_TRUE(labels.empty()); + }; + after_capture_t cleanup = [](sinsp* inspector) { // reset the value - param.m_inspector->set_container_labels_max_len(100); + inspector->set_container_labels_max_len(100); }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, before); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + before, + cleanup, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(saw_container_evt); } diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 8729a4f59b..18b2ba88ff 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -52,14 +52,23 @@ event_capture::event_capture(captured_event_callback_t captured_event_callback, m_inspector->set_auto_threads_purging(false); m_inspector->set_debug_mode(true); m_inspector->set_hostname_and_port_resolution_mode(false); - libsinsp_logger()->add_stdout_log(); m_param.m_inspector = m_inspector.get(); } -void event_capture::start(bool dump) { +void event_capture::start(bool dump, libsinsp::events::set& sc_set) { m_eventfd = eventfd(0, EFD_NONBLOCK); - open_engine(event_capture::get_engine(), {}); + + // To avoid back-pressure on the eventfd reads, do not attach them. + if(sc_set.empty()) { + for(int i = 0; i < PPM_SC_MAX; i++) { + auto sc_code = (ppm_sc_code)i; + if(sc_code != PPM_SC_READ && sc_code != PPM_SC_READV) { + sc_set.insert(sc_code); + } + } + } + open_engine(event_capture::get_engine(), sc_set); const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); @@ -194,7 +203,7 @@ void event_capture::open_engine(const std::string& engine_string, } #ifdef HAS_ENGINE_KMOD else if(!engine_string.compare(KMOD_ENGINE)) { - m_inspector->open_kmod(s_buffer_dim); + m_inspector->open_kmod(s_buffer_dim, events_sc_codes); } #endif #ifdef HAS_ENGINE_BPF @@ -204,12 +213,15 @@ void event_capture::open_engine(const std::string& engine_string, << '\n'; exit(EXIT_FAILURE); } - m_inspector->open_bpf(event_capture::get_engine_path(), s_buffer_dim); + m_inspector->open_bpf(event_capture::get_engine_path(), s_buffer_dim, events_sc_codes); } #endif #ifdef HAS_ENGINE_MODERN_BPF else if(!engine_string.compare(MODERN_BPF_ENGINE)) { - m_inspector->open_modern_bpf(s_buffer_dim); + m_inspector->open_modern_bpf(s_buffer_dim, + DEFAULT_CPU_FOR_EACH_BUFFER, + true, + events_sc_codes); } #endif else { diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index ae71d5cc05..203ddcad39 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -69,17 +69,27 @@ class event_capture { uint64_t thread_timeout_ns, uint64_t inactive_thread_scan_time_ns); - void start(bool dump); + void start(bool dump, libsinsp::events::set& sc_set); void stop(); void capture(); static void do_nothing(sinsp* inspector) {} + /*! + \brief Run `run_function` synchronously, and + then loop on all events calling filter on them, + and, for any event that matches the filter, + calls captured_event_callback. + Before starting the capture, before_open is called. + After closing the capture, before_close is called. + The default ppm_sc_set is the whole set minus `read` and `readv`. + */ static void run(const run_callback_t& run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, before_capture_t before_open = event_capture::do_nothing, after_capture_t before_close = event_capture::do_nothing, + libsinsp::events::set sc_set = {}, uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, @@ -92,7 +102,7 @@ class event_capture { thread_timeout_ns, inactive_thread_scan_time_ns); - capturing.start(dump); + capturing.start(dump, sc_set); run_function(capturing.m_inspector.get()); // signal main thread to end the capture @@ -103,11 +113,21 @@ class event_capture { capturing.stop(); } + /*! + \brief Run `run_function` **asynchronously**, while + looping on all events calling filter on them, + and, for any event that matches the filter, + calls captured_event_callback. + Before starting the capture, before_open is called. + After closing the capture, before_close is called. + The default ppm_sc_set is the whole set minus `read` and `readv`. + */ static void run(const run_callback_async_t& run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, before_capture_t before_open = event_capture::do_nothing, after_capture_t before_close = event_capture::do_nothing, + libsinsp::events::set sc_set = {}, uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, @@ -120,7 +140,7 @@ class event_capture { thread_timeout_ns, inactive_thread_scan_time_ns); - capturing.start(dump); + capturing.start(dump, sc_set); std::thread thread([&run_function, &capturing]() { run_function(); diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index ec3b3c672e..69b89e6f95 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -277,6 +277,7 @@ TEST_F(sys_call_test, forking_process_expired) { filter, event_capture::do_nothing, event_capture::do_nothing, + {}, 131072, 5 * ONE_SECOND_IN_NS, ONE_SECOND_IN_NS); @@ -741,7 +742,14 @@ TEST_F(sys_call_test, forking_main_thread_exit) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(3, callnum); } diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index 3b71b36fbb..a39211e596 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -538,7 +538,14 @@ TEST_F(sys_call_test, fs_readv) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(4, callnum); } @@ -1243,6 +1250,7 @@ TEST_F(sys_call_test, large_read_write) { filter, setup, event_capture::do_nothing, + libsinsp::events::all_sc_set(), 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, @@ -1361,6 +1369,7 @@ TEST_F(sys_call_test, large_readv_writev) { filter, setup, event_capture::do_nothing, + libsinsp::events::all_sc_set(), 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, diff --git a/test/libsinsp_e2e/process.cpp b/test/libsinsp_e2e/process.cpp index d65cdfcb0a..7991669f41 100644 --- a/test/libsinsp_e2e/process.cpp +++ b/test/libsinsp_e2e/process.cpp @@ -202,7 +202,14 @@ TEST_F(sys_call_test, process_signalfd_kill) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(7, callnum); } @@ -336,7 +343,14 @@ TEST_F(sys_call_test, process_inotify) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(3, callnum); } @@ -378,7 +392,7 @@ TEST(procinfo, process_not_existent) { TEST_F(sys_call_test, process_rlimit) { int callnum = 0; - + struct rlimit curr_rl; // // FILTER // @@ -387,21 +401,20 @@ TEST_F(sys_call_test, process_rlimit) { // // TEST CODE // - run_callback_t test = [](sinsp* inspector) { - struct rlimit rl; - sleep(1); - + run_callback_t test = [&](sinsp* inspector) { // Called directly because libc likes prlimit() syscall(SYS_getrlimit, RLIMIT_NOFILE, (struct rlimit*)33); - syscall(SYS_getrlimit, RLIMIT_NOFILE, &rl); - rl.rlim_cur = 500; - rl.rlim_max = 1000; - syscall(SYS_setrlimit, RLIMIT_NOFILE, &rl); - syscall(SYS_getrlimit, RLIMIT_NOFILE, &rl); + syscall(SYS_getrlimit, RLIMIT_NOFILE, &curr_rl); + + struct rlimit new_rl; + new_rl.rlim_cur = 5000; + new_rl.rlim_max = 10000; + syscall(SYS_setrlimit, RLIMIT_NOFILE, &new_rl); + syscall(SYS_getrlimit, RLIMIT_NOFILE, &new_rl); }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -419,8 +432,8 @@ TEST_F(sys_call_test, process_rlimit) { EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("res", false))); if(callnum == 7) { - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("cur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("max", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("cur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("max", false))); } } @@ -435,8 +448,8 @@ TEST_F(sys_call_test, process_rlimit) { EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("res", false))); if(callnum == 5) { - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("cur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("max", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("cur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("max", false))); } callnum++; @@ -463,8 +476,8 @@ TEST_F(sys_call_test, process_rlimit) { break; case 5: EXPECT_EQ(0, res); - EXPECT_EQ(500, newcur); - EXPECT_EQ(1000, newmax); + EXPECT_EQ(5000, newcur); + EXPECT_EQ(10000, newmax); EXPECT_EQ(-1, oldcur); EXPECT_EQ(-1, oldmax); break; @@ -472,14 +485,18 @@ TEST_F(sys_call_test, process_rlimit) { EXPECT_EQ(0, res); EXPECT_EQ(-1, newcur); EXPECT_EQ(-1, newmax); - EXPECT_EQ(500, oldcur); - EXPECT_EQ(1000, oldmax); + EXPECT_EQ(5000, oldcur); + EXPECT_EQ(10000, oldmax); break; } callnum++; } }; + after_capture_t cleanup = [&](sinsp* inspector) { + syscall(SYS_setrlimit, RLIMIT_NOFILE, &curr_rl); + }; + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); EXPECT_EQ(8, callnum); @@ -487,7 +504,6 @@ TEST_F(sys_call_test, process_rlimit) { TEST_F(sys_call_test, process_prlimit) { int callnum = 0; - struct rlimit tmprl; struct rlimit orirl; // @@ -503,8 +519,8 @@ TEST_F(sys_call_test, process_prlimit) { struct rlimit oldrl; syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &orirl); - newrl.rlim_cur = 500; - newrl.rlim_max = 1000; + newrl.rlim_cur = 5000; + newrl.rlim_max = 10000; syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, &newrl, &oldrl); syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &oldrl); }; @@ -532,8 +548,8 @@ TEST_F(sys_call_test, process_prlimit) { EXPECT_EQ((int64_t)orirl.rlim_max, std::stoll(e->get_param_value_str("oldmax", false))); } else if(callnum == 3) { - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("newcur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("newmax", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("newcur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("newmax", false))); EXPECT_EQ((int64_t)orirl.rlim_cur, std::stoll(e->get_param_value_str("oldcur", false))); EXPECT_EQ((int64_t)orirl.rlim_max, @@ -541,19 +557,20 @@ TEST_F(sys_call_test, process_prlimit) { } else if(callnum == 5) { EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("newcur", false))); EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("newmax", false))); - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("oldcur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("oldmax", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("oldcur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("oldmax", false))); } callnum++; } }; - if(syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &tmprl) != 0) { - return; - } + after_capture_t cleanup = [&](sinsp* inspector) { + syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, &orirl, NULL); + }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); EXPECT_EQ(6, callnum); } diff --git a/test/libsinsp_e2e/suppress_events.cpp b/test/libsinsp_e2e/suppress_events.cpp index 2e8c176036..243c0c645a 100644 --- a/test/libsinsp_e2e/suppress_events.cpp +++ b/test/libsinsp_e2e/suppress_events.cpp @@ -121,6 +121,7 @@ static void test_helper_quotactl(test_helper_args& hargs) { filter, before_open, before_close, + {}, 131072, 6000, 6000, diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index 3ea8722075..558668c039 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -496,7 +496,14 @@ TEST_F(sys_call_test, timerfd) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(3, callnum); } diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index b798befde0..23e861849e 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -275,6 +275,7 @@ void runtest(iotype iot, filter, before, event_capture::do_nothing, + libsinsp::events::all_sc_set(), 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, @@ -370,6 +371,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) filter, event_capture::do_nothing, event_capture::do_nothing, + {}, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index 63ab2e6413..f60d306226 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -403,10 +403,6 @@ void runtest_ipv4m(iotype iot, tee(-1, -1, 0, 0); }; - std::function log_param = [](const callback_param& param) { - // std::cerr << param.m_evt->get_name() << std::endl; - }; - // // OUTPUT VALIDATION // @@ -445,15 +441,12 @@ void runtest_ipv4m(iotype iot, if(!exit_no_close) { EXPECT_EQ(SERVER_PORT_STR, dst_port); } - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_LISTEN_E) { EXPECT_EQ("1", evt->get_param_value_str("backlog")); - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_LISTEN_X) { EXPECT_EQ("0", evt->get_param_value_str("res")); - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_ACCEPT4_6_E) { EXPECT_EQ("0", evt->get_param_value_str("flags")); @@ -480,7 +473,6 @@ void runtest_ipv4m(iotype iot, EXPECT_EQ(SERVER_PORT_STR, dst_port); } - log_param(param); callnum++; } @@ -493,9 +485,7 @@ void runtest_ipv4m(iotype iot, // recvfrom() and sets the address to NULL // if(evt->get_type() == PPME_SOCKET_SEND_E || evt->get_type() == PPME_SOCKET_RECV_E || - evt->get_type() == PPME_SOCKET_SENDTO_E || evt->get_type() == PPME_SOCKET_RECVFROM_E || - evt->get_type() == PPME_SYSCALL_READ_E || evt->get_type() == PPME_SYSCALL_WRITE_E || - evt->get_type() == PPME_SYSCALL_READV_E || evt->get_type() == PPME_SYSCALL_WRITEV_E) { + evt->get_type() == PPME_SOCKET_SENDTO_E || evt->get_type() == PPME_SOCKET_RECVFROM_E) { if(evt->get_type() == PPME_SOCKET_RECVFROM_E) { if(evt->get_param_value_str("tuple") != "") { EXPECT_EQ("NULL", evt->get_param_value_str("tuple")); @@ -516,11 +506,9 @@ void runtest_ipv4m(iotype iot, EXPECT_EQ(SERVER_PORT_STR, dst_port); } - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_RECV_X || - evt->get_type() == PPME_SOCKET_RECVFROM_X || - evt->get_type() == PPME_SYSCALL_READ_X) { + evt->get_type() == PPME_SOCKET_RECVFROM_X) { if(evt->get_type() == PPME_SOCKET_RECVFROM_X) { if(!parse_tuple(evt->get_param_value_str("tuple"), src_addr, @@ -551,14 +539,6 @@ void runtest_ipv4m(iotype iot, EXPECT_EQ(PAYLOAD, evt->get_param_value_str("data")); - log_param(param); - callnum++; - } else if(evt->get_type() == PPME_SYSCALL_READV_X) { - std::string ds = evt->get_param_value_str("data"); - - EXPECT_EQ(PAYLOAD, evt->get_param_value_str("data")); - - log_param(param); callnum++; } @@ -590,6 +570,7 @@ void runtest_ipv4m(iotype iot, filter, event_capture::do_nothing, event_capture::do_nothing, + {}, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, From 741d19355bbcf72ac556722d2710c736773beb38 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 30 Sep 2024 10:38:56 +0200 Subject: [PATCH 16/20] fix(userspace/libpman): try harder to avoid leaking fds. Signed-off-by: Federico Di Pierro --- userspace/libpman/src/configuration.c | 2 +- userspace/libpman/src/lifecycle.c | 12 ++++++++++++ userspace/libpman/src/ringbuffer.c | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/userspace/libpman/src/configuration.c b/userspace/libpman/src/configuration.c index 40e4e684fc..1f0e8ca26c 100644 --- a/userspace/libpman/src/configuration.c +++ b/userspace/libpman/src/configuration.c @@ -73,7 +73,7 @@ void pman_clear_state() { g_state.ringbuf_pos = 0; g_state.cons_pos = NULL; g_state.prod_pos = NULL; - g_state.inner_ringbuf_map_fd = 0; + g_state.inner_ringbuf_map_fd = -1; g_state.buffer_bytes_dim = 0; g_state.last_ring_read = -1; g_state.last_event_size = 0; diff --git a/userspace/libpman/src/lifecycle.c b/userspace/libpman/src/lifecycle.c index 68d0ad87be..51b2950976 100644 --- a/userspace/libpman/src/lifecycle.c +++ b/userspace/libpman/src/lifecycle.c @@ -67,6 +67,18 @@ void pman_close_probe() { g_state.stats = NULL; } + if(g_state.inner_ringbuf_map_fd != -1) { + close(g_state.inner_ringbuf_map_fd); + g_state.inner_ringbuf_map_fd = -1; + } + + for(int i = 0; i < MODERN_BPF_PROG_ATTACHED_MAX; i++) { + if(g_state.attached_progs_fds[i] != -1) { + close(g_state.attached_progs_fds[i]); + g_state.attached_progs_fds[i] = -1; + } + } + if(g_state.cons_pos) { free(g_state.cons_pos); g_state.cons_pos = NULL; diff --git a/userspace/libpman/src/ringbuffer.c b/userspace/libpman/src/ringbuffer.c index 4e4207b153..b99db59069 100644 --- a/userspace/libpman/src/ringbuffer.c +++ b/userspace/libpman/src/ringbuffer.c @@ -131,6 +131,7 @@ int pman_finalize_ringbuf_array_after_loading() { /* We don't need anymore the inner map, close it. */ close(g_state.inner_ringbuf_map_fd); + g_state.inner_ringbuf_map_fd = -1; /* Create ring buffer maps. */ for(int i = 0; i < g_state.n_required_buffers; i++) { From 52c4d31a3b4a8120039eb62b692ff780dbf59b71 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 30 Sep 2024 14:44:50 +0200 Subject: [PATCH 17/20] chore(test/libsinsp_e2e): enlarge drivers' buffer size to avoid event losses. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/event_capture.cpp | 2 +- test/libsinsp_e2e/unix_client_server.cpp | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 18b2ba88ff..748d34accd 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -28,7 +28,7 @@ limitations under the License. std::string event_capture::s_engine_string = KMOD_ENGINE; std::string event_capture::s_engine_path; -unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; +unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM * 4; event_capture::event_capture(captured_event_callback_t captured_event_callback, before_capture_t before_open, diff --git a/test/libsinsp_e2e/unix_client_server.cpp b/test/libsinsp_e2e/unix_client_server.cpp index a501b66f90..e123ab0aad 100644 --- a/test/libsinsp_e2e/unix_client_server.cpp +++ b/test/libsinsp_e2e/unix_client_server.cpp @@ -95,7 +95,6 @@ TEST_F(sys_call_test, unix_client_server) { ends_with(ti->m_args[0], "unix_client_server.py"); } } - return false; }; @@ -120,8 +119,6 @@ TEST_F(sys_call_test, unix_client_server) { captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* evt = param.m_evt; - // std::cout << evt->get_name() << std::endl; - if(evt->get_type() == PPME_SOCKET_CONNECT_X) { std::string tuple = evt->get_param_value_str("tuple"); std::string addrs = tuple.substr(0, tuple.find(" ")); @@ -251,7 +248,14 @@ TEST_F(sys_call_test, unix_client_server) { // // OUTPUT VALDATION // - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); EXPECT_FALSE(first_connect_or_accept_seen); EXPECT_EQ(8, callnum); } From b71424993bd09e465d30e650618b1d141e750c12 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 30 Sep 2024 16:18:19 +0200 Subject: [PATCH 18/20] fix(test/libsinsp_e2e): avoid possible heap use after free. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/forking.cpp | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 69b89e6f95..e745217f95 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -466,6 +466,10 @@ TEST_F(sys_call_test, forking_clone_nofs) { int flags = CLONE_FS | CLONE_VM; int drflags = PPM_CL_CLONE_FS | PPM_CL_CLONE_VM; + const int STACK_SIZE = 65536; /* Stack size for cloned child */ + char* stack; /* Start of stack buffer area */ + char* stackTop; /* End of stack buffer area */ + // // FILTER // @@ -477,10 +481,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { // TEST CODE // run_callback_t test = [&](sinsp* inspector) { - const int STACK_SIZE = 65536; /* Stack size for cloned child */ - char* stack; /* Start of stack buffer area */ - char* stackTop; /* End of stack buffer area */ - clone_params cp; /* Passed to child function */ + clone_params cp; /* Passed to child function */ int status; pid_t pid; @@ -520,7 +521,6 @@ TEST_F(sys_call_test, forking_clone_nofs) { close(cp.fd); sleep(1); - free(stack); }; // @@ -579,7 +579,10 @@ TEST_F(sys_call_test, forking_clone_nofs) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + after_capture_t cleanup = [&](sinsp* inspector) { free(stack); }; + + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); EXPECT_EQ(callnum, 4); } @@ -603,6 +606,10 @@ TEST_F(sys_call_test, forking_clone_cwd) { int drflags = PPM_CL_CLONE_VM | PPM_CL_CLONE_FS | PPM_CL_CLONE_FILES | PPM_CL_CLONE_SIGHAND | PPM_CL_CLONE_THREAD; + const int STACK_SIZE = 65536; /* Stack size for cloned child */ + char* stack; /* Start of stack buffer area */ + char* stackTop; /* End of stack buffer area */ + // // FILTER // @@ -612,10 +619,6 @@ TEST_F(sys_call_test, forking_clone_cwd) { // TEST CODE // run_callback_t test = [&](sinsp* inspector) { - const int STACK_SIZE = 65536; /* Stack size for cloned child */ - char* stack; /* Start of stack buffer area */ - char* stackTop; /* End of stack buffer area */ - ASSERT_TRUE(getcwd(oriwd, 1024) != NULL); /* Allocate stack for child */ @@ -636,8 +639,6 @@ TEST_F(sys_call_test, forking_clone_cwd) { std::string tmps = getcwd(bcwd, 256); ASSERT_TRUE(chdir(oriwd) == 0); - - free(stack); }; // @@ -677,7 +678,10 @@ TEST_F(sys_call_test, forking_clone_cwd) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + after_capture_t cleanup = [&](sinsp* inspector) { free(stack); }; + + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); EXPECT_EQ(3, callnum); } From cf084be17d0d4d7cd22967f5591fb71412d3ed1e Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Tue, 1 Oct 2024 12:08:41 +0200 Subject: [PATCH 19/20] chore(test/libsinsp_e2e): improve test reliability. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/forking.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index e745217f95..29eada31d0 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -392,7 +392,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -519,12 +519,10 @@ TEST_F(sys_call_test, forking_clone_nofs) { FAIL(); close(cp.fd); - - sleep(1); }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -583,6 +581,7 @@ TEST_F(sys_call_test, forking_clone_nofs) { ASSERT_NO_FATAL_FAILURE( { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); + EXPECT_EQ(callnum, 4); } @@ -634,15 +633,17 @@ TEST_F(sys_call_test, forking_clone_cwd) { FAIL(); } - usleep(500); + // Give new thread enough time to exit + sleep(1); + // The cloned child called chdir("/"); we expect to retrieve "/" here. std::string tmps = getcwd(bcwd, 256); ASSERT_TRUE(chdir(oriwd) == 0); }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -668,9 +669,15 @@ TEST_F(sys_call_test, forking_clone_cwd) { if(ti->m_tid == ptid) { if(callnum > 1) { + // last getcwd call in the test EXPECT_EQ(bcwd, ti->get_cwd()); + EXPECT_EQ(bcwd, std::string("/")); + } else { + // first getcwd call in the test + EXPECT_EQ(std::string(oriwd) + "/", ti->get_cwd()); } } else if(ti->m_tid == ctid) { + // getcwd call by the child EXPECT_EQ("/", ti->get_cwd()); } From a904e2eefc931efce1458611755aba4561271954 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Tue, 1 Oct 2024 12:59:49 +0200 Subject: [PATCH 20/20] fix(test/libsinsp_e2e): make container_clone_nspid related tests more reliable. Signed-off-by: Federico Di Pierro --- test/libsinsp_e2e/container/container.cpp | 40 ++++++++++------------- test/libsinsp_e2e/forking.cpp | 8 ++--- 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 02121f1e2c..7d22be2433 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -119,11 +119,6 @@ TEST_F(sys_call_test, container_cgroups) { } static int clone_callback(void* arg) { - // Here we need 2 sleeps instead of once because, for some reason, - // we miss the first one. This problem is *probably* related to the - // fact that before we created a brand new inspector for each test but - // not we keep the same and start/stop the capture. - sleep(1); sleep(1); return 0; } @@ -195,21 +190,6 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { int flags = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD | CLONE_NEWPID; bool done = false; - const int STACK_SIZE = 65536; - char* stack; - char* stack_top; - - stack = (char*)malloc(STACK_SIZE); - if(stack == NULL) { - FAIL(); - } - stack_top = stack + STACK_SIZE; - - ctid = clone(clone_callback, stack_top, flags, NULL); - if(ctid == -1) { - FAIL(); - } - // // FILTER // @@ -218,7 +198,24 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { // // TEST CODE // - run_callback_t test = [&](sinsp* inspector) { waitpid(ctid, NULL, 0); }; + run_callback_t test = [&](sinsp* inspector) { + const int STACK_SIZE = 65536; + char* stack; + char* stack_top; + + stack = (char*)malloc(STACK_SIZE); + if(stack == NULL) { + FAIL(); + } + stack_top = stack + STACK_SIZE; + + ctid = clone(clone_callback, stack_top, flags, NULL); + if(ctid == -1) { + FAIL(); + } + waitpid(ctid, NULL, 0); + free(stack); + }; // // OUTPUT VALDATION @@ -238,7 +235,6 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { event_capture::do_nothing, libsinsp::events::sinsp_state_sc_set()); }); - free(stack); ASSERT_TRUE(done); } diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 29eada31d0..0035cd676a 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -141,7 +141,7 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { // Wait for 5 seconds to make sure the process will still // exist when the sinsp will do the lookup to /proc // - usleep(5000000); + sleep(5); close(fd); _exit(xstatus); // child exits with specific return code } else // fork() returns new pid to the parent process @@ -696,7 +696,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { TEST_F(sys_call_test, forking_main_thread_exit) { int evtnum = 0; int callnum = 0; - int fd; + int64_t fd; pid_t cpid; // parent tid event_filter_t filter = [&](sinsp_evt* evt) { @@ -734,13 +734,13 @@ TEST_F(sys_call_test, forking_main_thread_exit) { if(param.m_evt->get_type() == PPME_SYSCALL_OPEN_X) { if(param.m_evt->get_param_value_str("name") == "/etc/passwd") { EXPECT_EQ("/etc/passwd", param.m_evt->get_param_value_str("fd")); - fd = *(int64_t*)param.m_evt->get_param(0)->m_val; + fd = param.m_evt->get_param(0)->as(); ++callnum; } } else if(param.m_evt->get_type() == PPME_SYSCALL_OPENAT_2_X) { if(param.m_evt->get_param_value_str("name") == "/etc/passwd") { EXPECT_EQ("/etc/passwd", param.m_evt->get_param_value_str("fd")); - memcpy(&fd, (int64_t*)param.m_evt->get_param(0)->m_val, sizeof(fd)); + fd = param.m_evt->get_param(0)->as(); ++callnum; } } else if(param.m_evt->get_type() == PPME_PROCEXIT_1_E && param.m_evt->get_tid() == cpid) {