Skip to content

Commit 1445692

Browse files
arkqpull[bot]
authored andcommitted
[Linux] Fix event loop task consecutive start/stop (#26195)
* [Linux] Fix event loop task consecutive start/stop * Wait for lambdas before stopping loop task * Add comment for sleep() usage in test
1 parent 4dcb4f0 commit 1445692

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

src/include/platform/internal/GenericPlatformManagerImpl_POSIX.ipp

+4
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ CHIP_ERROR GenericPlatformManagerImpl_POSIX<ImplClass>::_InitChipStack()
5959
// Call up to the base class _InitChipStack() to perform the bulk of the initialization.
6060
ReturnErrorOnFailure(GenericPlatformManagerImpl<ImplClass>::_InitChipStack());
6161

62+
mShouldRunEventLoop.store(true, std::memory_order_relaxed);
63+
6264
int ret = pthread_cond_init(&mEventQueueStoppedCond, nullptr);
6365
VerifyOrReturnError(ret == 0, CHIP_ERROR_POSIX(ret));
6466

@@ -225,6 +227,8 @@ CHIP_ERROR GenericPlatformManagerImpl_POSIX<ImplClass>::_StartEventLoopTask()
225227
VerifyOrReturnError(err == 0, CHIP_ERROR_POSIX(err));
226228
#endif
227229

230+
mShouldRunEventLoop.store(true, std::memory_order_relaxed);
231+
228232
//
229233
// We need to grab the lock here since we have to protect setting
230234
// mHasValidChipTask, which will be read right away upon creating the

src/platform/tests/TestPlatformMgr.cpp

+44-4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#include <stdlib.h>
2929
#include <string.h>
3030

31+
#include <atomic>
32+
3133
#include <lib/support/CHIPMem.h>
3234
#include <lib/support/CodeUtils.h>
3335
#include <lib/support/UnitTestRegistration.h>
@@ -55,14 +57,52 @@ static void TestPlatformMgr_InitShutdown(nlTestSuite * inSuite, void * inContext
5557

5658
static void TestPlatformMgr_BasicEventLoopTask(nlTestSuite * inSuite, void * inContext)
5759
{
60+
std::atomic<int> counterRun{ 0 };
61+
5862
CHIP_ERROR err = PlatformMgr().InitChipStack();
5963
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
6064

61-
err = PlatformMgr().StartEventLoopTask();
62-
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
65+
// Start/stop the event loop task a few times.
66+
for (size_t i = 0; i < 3; i++)
67+
{
68+
err = PlatformMgr().StartEventLoopTask();
69+
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
70+
71+
std::atomic<int> counterSync{ 2 };
72+
73+
// Verify that the event loop will not exit until we tell it to by
74+
// scheduling few lambdas (for the test to pass, the event loop will
75+
// have to process more than one event).
76+
DeviceLayer::SystemLayer().ScheduleLambda([&]() {
77+
counterRun++;
78+
counterSync--;
79+
});
80+
81+
// Sleep for a short time to allow the event loop to process the
82+
// scheduled event and go to idle state. Without this sleep, the
83+
// event loop may process both scheduled lambdas during single
84+
// iteration of the event loop which would defeat the purpose of
85+
// this test on POSIX platforms where the event loop is implemented
86+
// using a "do { ... } while (shouldRun)" construct.
87+
chip::test_utils::SleepMillis(10);
88+
89+
DeviceLayer::SystemLayer().ScheduleLambda([&]() {
90+
counterRun++;
91+
counterSync--;
92+
});
93+
94+
// Wait for the event loop to process the scheduled events.
95+
// Note, that we can not use any synchronization primitives like
96+
// condition variables or barriers, because the test has to compile
97+
// on all platforms. Instead we use a busy loop with a timeout.
98+
for (size_t t = 0; counterSync != 0 && t < 1000; t++)
99+
chip::test_utils::SleepMillis(1);
100+
101+
err = PlatformMgr().StopEventLoopTask();
102+
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
103+
}
63104

64-
err = PlatformMgr().StopEventLoopTask();
65-
NL_TEST_ASSERT(inSuite, err == CHIP_NO_ERROR);
105+
NL_TEST_ASSERT(inSuite, counterRun == (3 * 2));
66106

67107
PlatformMgr().Shutdown();
68108
}

0 commit comments

Comments
 (0)