如何无需优雅关闭即可终止FreeRTOS仿真并获取GTest测试结果
解决方案
方案1:测试完成后直接终止整个进程(最优,符合你的需求)
你不需要优雅关闭FreeRTOS,所以直接在GTest跑完所有用例、拿到结果后,调用系统级进程退出接口强制结束整个进程即可,操作系统会自动回收所有线程资源,不会出现等待FreeRTOS线程的问题。
修改你的main函数代码如下:
int main(int argc,char *argv[]) { ::testing::InitGoogleTest(&argc, argv); int res = RUN_ALL_TESTS(); // 拿到测试结果后直接终止进程,跳过等待其他线程的逻辑 #ifdef _WIN32 ::ExitProcess(res); #else ::_exit(res); #endif // 以下代码永远不会执行 return res; }
这个方案的优势:
- 实现最简单,不需要修改现有测试套件逻辑
- 测试结果返回值完全正确,RUN_ALL_TESTS已经计算完所有用例的执行结果,将结果作为进程退出码返回,CI/测试脚本可以正常识别测试结果
- 不存在资源泄漏问题,进程退出后操作系统会回收所有占用的内存、线程等资源
方案2:强制终止所有FreeRTOS仿真产生的线程
如果你需要保留正常的main函数退出逻辑,可以在TearDownTestSuite中补充枚举、终止所有FreeRTOS仿真创建的原生线程的逻辑:
你之前的方案只终止了FreeRTOS调度器所在的std::thread线程,但FreeRTOS仿真层为了模拟多任务,会自行创建多个原生线程,这些线程没有被终止才导致程序无法退出。可以按如下逻辑修改:
void TestFixture::TearDownTestSuite() { if (m_pSim) { // 先清理FreeRTOS层面的任务 const auto vecTaskInfo = getAllRunningFreeRTOSTasks(); for (const auto& singleTask : vecTaskInfo) { vTaskSuspend(singleTask.xHandle); vTaskDelete(singleTask.xHandle); } vTaskSuspendAll(); #ifdef _WIN32 // Windows平台枚举所有当前进程的线程,终止除了当前主线程之外的所有线程 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (hSnapshot != INVALID_HANDLE_VALUE) { THREADENTRY32 te; te.dwSize = sizeof(te); DWORD currentPid = GetCurrentProcessId(); DWORD currentTid = GetCurrentThreadId(); if (Thread32First(hSnapshot, &te)) { do { if (te.th32OwnerProcessID == currentPid && te.th32ThreadID != currentTid) { HANDLE hThread = OpenThread(THREAD_TERMINATE, FALSE, te.th32ThreadID); if (hThread) { TerminateThread(hThread, 0); CloseHandle(hThread); } } } while (Thread32Next(hSnapshot, &te)); } CloseHandle(hSnapshot); } #else // Linux平台可通过pthread_kill或者tgkill终止所有非主线程,逻辑类似 #endif m_pSim->detach(); } }
注意事项
两种方案都属于强制终止的操作,不会执行C++的栈展开、全局对象析构逻辑,但对于自动化测试场景来说完全可用,不会影响测试结果的正确性。
内容的提问来源于stack exchange,提问作者user8694474
相关产品推荐
相关产品推荐

