From 4e6c5b4f607ad6caab2e2971fc327e8a38178885 Mon Sep 17 00:00:00 2001 From: PengZheng Date: Sun, 3 Sep 2023 20:21:21 +0800 Subject: [PATCH] Update shell test to avoid potential deadlock This change resolves the potential deadlock issue (#629) when calling quit/stop commands. celix_bundleContext_trackService is utilized instead of the old `celix_bundleContext_useServiceWithOptions` method. --- .../shell/shell/gtest/src/ShellTestSuite.cc | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/bundles/shell/shell/gtest/src/ShellTestSuite.cc b/bundles/shell/shell/gtest/src/ShellTestSuite.cc index 6f85f70d2..8c43e016d 100644 --- a/bundles/shell/shell/gtest/src/ShellTestSuite.cc +++ b/bundles/shell/shell/gtest/src/ShellTestSuite.cc @@ -17,6 +17,7 @@ * under the License. */ +#include #include #include @@ -63,20 +64,24 @@ TEST_F(ShellTestSuite, shellBundleInstalledTest) { } static void callCommand(std::shared_ptr& ctx, const char *cmdLine, bool cmdShouldSucceed) { - celix_service_use_options_t opts{}; - struct callback_data { const char *cmdLine{}; bool cmdShouldSucceed{}; + std::promise barrier{}; + celix_bundle_context_t* context{}; + long tracker{-1}; }; + // Note that using celix_bundleContext_useServiceWithOptions to call command quit/stop may result in deadlock. + // For more on this, see https://github.com/apache/celix/issues/629 struct callback_data data{}; data.cmdLine = cmdLine; data.cmdShouldSucceed = cmdShouldSucceed; - - opts.filter.serviceName = CELIX_SHELL_SERVICE_NAME; - opts.callbackHandle = static_cast(&data); - opts.waitTimeoutInSeconds = 1.0; - opts.use = [](void *handle, void *svc) { + data.context = ctx.get(); + data.tracker = celix_bundleContext_trackService(ctx.get(), CELIX_SHELL_SERVICE_NAME, + static_cast(&data), [](void * handle, void * svc) { + if (svc == nullptr) { + return; + } auto *shell = static_cast(svc); auto *d = static_cast(handle); EXPECT_TRUE(shell != nullptr); @@ -86,9 +91,10 @@ static void callCommand(std::shared_ptr& ctx, const char } else { EXPECT_NE(CELIX_SUCCESS, status) << "Command '" << d->cmdLine << "' should not succeed"; } - }; - bool called = celix_bundleContext_useServiceWithOptions(ctx.get(), &opts); - EXPECT_TRUE(called); + celix_bundleContext_stopTracker(d->context, d->tracker); + d->barrier.set_value(); + }); + data.barrier.get_future().wait(); } TEST_F(ShellTestSuite, testAllCommandsAreCallable) {