Merge lp:~michihenning/unity-scopes-api/fix-reaper-finished into lp:unity-scopes-api/devel

Proposed by Michi Henning
Status: Merged
Approved by: Michi Henning
Approved revision: 427
Merged at revision: 428
Proposed branch: lp:~michihenning/unity-scopes-api/fix-reaper-finished
Merge into: lp:unity-scopes-api/devel
Diff against target: 331 lines (+238/-8)
10 files modified
include/unity/scopes/SearchListenerBase.h (+5/-7)
src/scopes/internal/ReplyObject.cpp (+6/-1)
test/gtest/scopes/CMakeLists.txt (+1/-0)
test/gtest/scopes/ReplyReaper/CMakeLists.txt (+10/-0)
test/gtest/scopes/ReplyReaper/NoReplyScope.cpp (+61/-0)
test/gtest/scopes/ReplyReaper/NoReplyScope.h (+33/-0)
test/gtest/scopes/ReplyReaper/Registry.ini.in (+6/-0)
test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp (+107/-0)
test/gtest/scopes/ReplyReaper/Runtime.ini.in (+7/-0)
test/gtest/scopes/ReplyReaper/Zmq.ini.in (+2/-0)
To merge this branch: bzr merge lp:~michihenning/unity-scopes-api/fix-reaper-finished
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michal Hruby (community) Approve
Review via email: mp+228600@code.launchpad.net

Commit message

Fixed ReplyObject::finished() to call disconnect() last. When the
reaper called finished(), the early disconnect() dropped the
last shared_ptr to this instance, causing the call to
listener_base_->finished() to go into an already-destroyed
instance. Added test for this case.

Description of the change

Fixed ReplyObject::finished() to call disconnect() last. When the
reaper called finished(), the early disconnect() dropped the
last shared_ptr to this instance, causing the call to
listener_base_->finished() to go into an already-destroyed
instance. Added test for this case.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michal Hruby (mhr3) wrote :

+1

Revision history for this message
Michal Hruby (mhr3) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
427. By Michi Henning

Fixed compilation error due to changes on devel and fixed incorrect test name.

Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Autolanding.
Approved revid is not set in launchpad. This is most likely a launchpad issue and re-approve should fix it. There is also a chance (although a very small one) this is a permission problem of the ps-jenkins bot.
http://jenkins.qa.ubuntu.com/job/unity-scopes-api-devel-autolanding/370/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-scopes-api-devel-utopic-amd64-autolanding/194
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-scopes-api-devel-utopic-armhf-autolanding/193
        deb: http://jenkins.qa.ubuntu.com/job/unity-scopes-api-devel-utopic-armhf-autolanding/193/artifact/work/output/*zip*/output.zip
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-scopes-api-devel-utopic-i386-autolanding/194

review: Needs Fixing (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

Re-approving for Jenkins.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'include/unity/scopes/SearchListenerBase.h'
--- include/unity/scopes/SearchListenerBase.h 2014-07-28 08:51:57 +0000
+++ include/unity/scopes/SearchListenerBase.h 2014-07-30 21:36:19 +0000
@@ -19,13 +19,14 @@
19#ifndef UNITY_SCOPES_SEARCHLISTENERBASE_H19#ifndef UNITY_SCOPES_SEARCHLISTENERBASE_H
20#define UNITY_SCOPES_SEARCHLISTENERBASE_H20#define UNITY_SCOPES_SEARCHLISTENERBASE_H
2121
22#include <unity/scopes/Annotation.h>
23#include <unity/scopes/CategorisedResult.h>
24#include <unity/scopes/Category.h>
25#include <unity/scopes/Department.h>
26#include <unity/scopes/FilterBase.h>
22#include <unity/scopes/ListenerBase.h>27#include <unity/scopes/ListenerBase.h>
23#include <unity/util/DefinesPtrs.h>28#include <unity/util/DefinesPtrs.h>
24#include <unity/util/NonCopyable.h>29#include <unity/util/NonCopyable.h>
25#include <unity/scopes/Category.h>
26#include <unity/scopes/Annotation.h>
27#include <unity/scopes/Department.h>
28#include <unity/scopes/FilterBase.h>
2930
30#include <string>31#include <string>
3132
@@ -35,9 +36,6 @@
35namespace scopes36namespace scopes
36{37{
3738
38class CategorisedResult;
39class FilterState;
40
41namespace experimental39namespace experimental
42{40{
43class Annotation;41class Annotation;
4442
=== modified file 'src/scopes/internal/ReplyObject.cpp'
--- src/scopes/internal/ReplyObject.cpp 2014-07-28 09:55:08 +0000
+++ src/scopes/internal/ReplyObject.cpp 2014-07-30 21:36:19 +0000
@@ -149,7 +149,6 @@
149 // Only one thread can reach this point, any others were thrown out above.149 // Only one thread can reach this point, any others were thrown out above.
150150
151 reap_item_->destroy();151 reap_item_->destroy();
152 disconnect(); // Disconnect self from middleware, if this hasn't happened yet.
153152
154 // Wait until all currently executing calls to push() have completed.153 // Wait until all currently executing calls to push() have completed.
155 unique_lock<mutex> lock(mutex_);154 unique_lock<mutex> lock(mutex_);
@@ -175,6 +174,12 @@
175 cerr << "ReplyObject::finished(): unknown exception" << endl;174 cerr << "ReplyObject::finished(): unknown exception" << endl;
176 // TODO: log error175 // TODO: log error
177 }176 }
177
178 // Disconnect self from middleware, if this hasn't happened yet.
179 // We do this last because disconnect() can trigger
180 // the destructor of this instance (if finished() is called
181 // by the reaper, for example).
182 disconnect();
178}183}
179184
180void ReplyObject::info(OperationInfo const& op_info) noexcept185void ReplyObject::info(OperationInfo const& op_info) noexcept
181186
=== modified file 'test/gtest/scopes/CMakeLists.txt'
--- test/gtest/scopes/CMakeLists.txt 2014-07-29 09:33:53 +0000
+++ test/gtest/scopes/CMakeLists.txt 2014-07-30 21:36:19 +0000
@@ -17,6 +17,7 @@
17add_subdirectory(RadioButtonsFilter)17add_subdirectory(RadioButtonsFilter)
18add_subdirectory(RangeInputFilter)18add_subdirectory(RangeInputFilter)
19add_subdirectory(RatingFilter)19add_subdirectory(RatingFilter)
20add_subdirectory(ReplyReaper)
20add_subdirectory(SwitchFilter)21add_subdirectory(SwitchFilter)
21add_subdirectory(ValueSliderFilter)22add_subdirectory(ValueSliderFilter)
22add_subdirectory(PreviewWidget)23add_subdirectory(PreviewWidget)
2324
=== added directory 'test/gtest/scopes/ReplyReaper'
=== added file 'test/gtest/scopes/ReplyReaper/CMakeLists.txt'
--- test/gtest/scopes/ReplyReaper/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/CMakeLists.txt 2014-07-30 21:36:19 +0000
@@ -0,0 +1,10 @@
1configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
2configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
3configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
4
5add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}")
6
7add_executable(ReplyReaper_test ReplyReaper_test.cpp NoReplyScope.cpp)
8target_link_libraries(ReplyReaper_test ${TESTLIBS})
9
10add_test(ReplyReaper ReplyReaper_test)
011
=== added file 'test/gtest/scopes/ReplyReaper/NoReplyScope.cpp'
--- test/gtest/scopes/ReplyReaper/NoReplyScope.cpp 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/NoReplyScope.cpp 2014-07-30 21:36:19 +0000
@@ -0,0 +1,61 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include "NoReplyScope.h"
20
21#include <unity/scopes/ScopeBase.h>
22
23#include <thread>
24
25#include <gtest/gtest.h>
26
27using namespace std;
28using namespace unity::scopes;
29
30namespace
31{
32
33class Query : public SearchQueryBase
34{
35public:
36 Query(CannedQuery const& query, SearchMetadata const& metadata)
37 : SearchQueryBase(query, metadata)
38 {
39 }
40
41 virtual void run(SearchReplyProxy const&) override
42 {
43 this_thread::sleep_for(chrono::seconds(3));
44 }
45
46 virtual void cancelled() override
47 {
48 }
49};
50
51} // namespace
52
53SearchQueryBase::UPtr NoReplyScope::search(CannedQuery const& query, SearchMetadata const& metadata)
54{
55 return SearchQueryBase::UPtr(new Query(query, metadata));
56}
57
58PreviewQueryBase::UPtr NoReplyScope::preview(Result const&, ActionMetadata const&)
59{
60 return nullptr; // Not called
61}
062
=== added file 'test/gtest/scopes/ReplyReaper/NoReplyScope.h'
--- test/gtest/scopes/ReplyReaper/NoReplyScope.h 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/NoReplyScope.h 2014-07-30 21:36:19 +0000
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#ifndef TEST_NOREPLYSCOPE_H
20#define TEST_NOREPLYSCOPE_H
21
22#include <unity/scopes/ScopeBase.h>
23
24class NoReplyScope : public unity::scopes::ScopeBase
25{
26public:
27 virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
28 unity::scopes::SearchMetadata const&) override;
29 virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
30 unity::scopes::ActionMetadata const&) override;
31};
32
33#endif
034
=== added file 'test/gtest/scopes/ReplyReaper/Registry.ini.in'
--- test/gtest/scopes/ReplyReaper/Registry.ini.in 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/Registry.ini.in 2014-07-30 21:36:19 +0000
@@ -0,0 +1,6 @@
1[Registry]
2Middleware = Zmq
3Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
4Scope.InstallDir = /unused
5Click.InstallDir = /unused
6Scoperunner.Path = /unused
07
=== added file 'test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp'
--- test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp 2014-07-30 21:36:19 +0000
@@ -0,0 +1,107 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 3 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authored by: Michi Henning <michi.henning@canonical.com>
17 */
18
19#include <unity/scopes/internal/RegistryObject.h>
20#include <unity/scopes/internal/RuntimeImpl.h>
21#include <unity/scopes/internal/ScopeImpl.h>
22
23#include <boost/algorithm/string.hpp>
24#include <gtest/gtest.h>
25
26#include "NoReplyScope.h"
27
28using namespace std;
29using namespace unity::scopes;
30using namespace unity::scopes::internal;
31
32class NullReceiver : public SearchListenerBase
33{
34public:
35 NullReceiver()
36 : query_complete_(false)
37 {
38 }
39
40 virtual void push(CategorisedResult /* result */) override
41 {
42 }
43
44 virtual void finished(CompletionDetails const& details) override
45 {
46 // Check that finished() was called by the reaper.
47 EXPECT_EQ(CompletionDetails::Error, details.status()) << details.message();
48 EXPECT_TRUE(boost::starts_with(details.message(), "No activity on ReplyObject for scope"));
49 lock_guard<mutex> lock(mutex_);
50 query_complete_ = true;
51 cond_.notify_all();
52 }
53
54 void wait_until_finished()
55 {
56 unique_lock<mutex> lock(mutex_);
57 cond_.wait(lock, [this] { return this->query_complete_; });
58 }
59
60private:
61 bool query_complete_;
62 mutex mutex_;
63 condition_variable cond_;
64};
65
66std::shared_ptr<core::posix::SignalTrap>
67 trap(core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_chld}));
68std::unique_ptr<core::posix::ChildProcess::DeathObserver>
69 death_observer(core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap(trap));
70
71RuntimeImpl::SPtr run_test_registry()
72{
73 RuntimeImpl::SPtr runtime = RuntimeImpl::create("TestRegistry", TEST_DIR "/Runtime.ini");
74 MiddlewareBase::SPtr middleware = runtime->factory()->create("TestRegistry", "Zmq", "Zmq.ini");
75 RegistryObject::SPtr reg_obj(std::make_shared<RegistryObject>(*death_observer, std::make_shared<Executor>(), middleware));
76 middleware->add_registry_object("TestRegistry", reg_obj);
77 return runtime;
78}
79
80void scope_thread(Runtime::SPtr const& rt, string const& runtime_ini_file)
81{
82 NoReplyScope scope;
83 rt->run_scope(&scope, runtime_ini_file, "");
84}
85
86TEST(ReplyReaper, reap)
87{
88 auto reg_rt = run_test_registry();
89
90 Runtime::SPtr no_reply_rt = move(Runtime::create_scope_runtime("NoReplyScope", TEST_DIR "/Runtime.ini"));
91 std::thread scope_t(scope_thread, no_reply_rt, TEST_DIR "/Runtime.ini");
92
93 // Run a query in the scope. The query will do nothing for 3 seconds,
94 // but the reaper will reap after at most 2 seconds.
95 auto rt = internal::RuntimeImpl::create("", TEST_DIR "/Runtime.ini");
96 auto mw = rt->factory()->create("NoReplyScope", "Zmq", TEST_DIR "/Zmq.ini");
97 mw->start();
98 auto proxy = mw->create_scope_proxy("NoReplyScope");
99 auto scope = internal::ScopeImpl::create(proxy, rt.get(), "NoReplyScope");
100
101 auto receiver = make_shared<NullReceiver>();
102 scope->search("test", SearchMetadata("en", "phone"), receiver);
103 receiver->wait_until_finished();
104
105 no_reply_rt->destroy();
106 scope_t.join();
107}
0108
=== added file 'test/gtest/scopes/ReplyReaper/Runtime.ini.in'
--- test/gtest/scopes/ReplyReaper/Runtime.ini.in 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/Runtime.ini.in 2014-07-30 21:36:19 +0000
@@ -0,0 +1,7 @@
1[Runtime]
2Registry.Identity = TestRegistry
3Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Registry.ini
4Reap.Expiry = 2
5Reap.Interval = 1
6Default.Middleware = Zmq
7Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
08
=== added file 'test/gtest/scopes/ReplyReaper/Zmq.ini.in'
--- test/gtest/scopes/ReplyReaper/Zmq.ini.in 1970-01-01 00:00:00 +0000
+++ test/gtest/scopes/ReplyReaper/Zmq.ini.in 2014-07-30 21:36:19 +0000
@@ -0,0 +1,2 @@
1[Zmq]
2EndpointDir = /tmp

Subscribers

People subscribed via source and target branches

to all changes: