Skip to content

Commit

Permalink
static ServiceTracker object crashes in ServiceTracker::Close() (CppM…
Browse files Browse the repository at this point in the history
…icroServices#283)

Fixes CppMicroServices#281 
Prevent a crash when destroying a global ServiceTracker
Fixed documentation for exceptions
  • Loading branch information
jeffdiclemente authored and Aurelien Labrosse committed May 20, 2019
1 parent 0872791 commit fe08fa6
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 2 deletions.
9 changes: 8 additions & 1 deletion framework/include/cppmicroservices/ServiceTracker.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,9 +194,12 @@ class ServiceTracker : protected ServiceTrackerCustomizer<S,T>
* <code>ServiceTracker</code> was created are now tracked by this
* <code>ServiceTracker</code>.
*
* @throws std::logic_error If the <code>BundleContext</code>
* @throws std::runtime_error If the <code>BundleContext</code>
* with which this <code>ServiceTracker</code> was created is no
* longer valid.
* @throws std::runtime_error If the LDAP filter used to construct
* the <code>ServiceTracker</code> contains an invalid filter
* expression that cannot be parsed.
*/
virtual void Open();

Expand All @@ -210,6 +213,10 @@ class ServiceTracker : protected ServiceTrackerCustomizer<S,T>
* <p>
* This implementation calls GetServiceReferences() to get the list
* of tracked services to remove.
*
* @throws std::runtime_error If the <code>BundleContext</code>
* with which this <code>ServiceTracker</code> was created is no
* longer valid.
*/
virtual void Close();

Expand Down
6 changes: 5 additions & 1 deletion framework/include/cppmicroservices/detail/ServiceTracker.tpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ namespace cppmicroservices {
template<class S, class T>
ServiceTracker<S,T>::~ServiceTracker()
{
Close();
try
{
Close();
}
catch (...) {}
}

#ifdef _MSC_VER
Expand Down
1 change: 1 addition & 0 deletions framework/src/bundle/BundleContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ BundleContext& BundleContext::operator=(std::nullptr_t)

std::shared_ptr<detail::LogSink> BundleContext::GetLogSink() const
{
d->CheckValid();
return d->bundle->coreCtx->sink->shared_from_this();
}

Expand Down
1 change: 1 addition & 0 deletions framework/test/gtest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ include_directories(
set(_gtest_tests
AnyMapTest.cpp
BundleVersionTest.cpp
GlobalServiceTrackerTest.cpp
LDAPExprTest.cpp
LDAPFilterTest.cpp
UtilsTest.cpp
Expand Down
60 changes: 60 additions & 0 deletions framework/test/gtest/GlobalServiceTrackerTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*=============================================================================
Library: CppMicroServices
Copyright (c) The CppMicroServices developers. See the COPYRIGHT
file at the top-level directory of this distribution and at
https://github.com/CppMicroServices/CppMicroServices/COPYRIGHT .
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
=============================================================================*/

#include "cppmicroservices/GlobalConfig.h"

#include "cppmicroservices/Framework.h"
#include "cppmicroservices/FrameworkEvent.h"
#include "cppmicroservices/FrameworkFactory.h"
#include <cppmicroservices/ServiceInterface.h>
#include "cppmicroservices/ServiceTracker.h"

#include "gtest/gtest.h"

#include <memory>

// A dummy interface to use with service trackers
namespace {
class Foo {
public:
virtual ~Foo() {}
};
}

// Since the Foo interface is embedded in the test executable, its symbols are
// not exported. Using CPPMICROSERVICES_DECLARE_SERVICE_INTERFACE ensures that
// the symbols are exported correctly for use by CppMicroServices.
CPPMICROSERVICES_DECLARE_SERVICE_INTERFACE(Foo, "org.cppmicroservices.test.servicetracker.Foo");

TEST(GlobalServiceTrackerTest, Destroy)
{
auto f = cppmicroservices::FrameworkFactory().NewFramework();
ASSERT_TRUE(f);
f.Start();

static std::shared_ptr<cppmicroservices::ServiceTracker<Foo>> globalTracker(std::make_shared<cppmicroservices::ServiceTracker<Foo>>(f.GetBundleContext()));
globalTracker->Open();

f.Stop();
f.WaitForStop(std::chrono::milliseconds::zero());
// A test failure results in the executable crashing with an access violation.
}

0 comments on commit fe08fa6

Please sign in to comment.