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
1=== modified file 'include/unity/scopes/SearchListenerBase.h'
2--- include/unity/scopes/SearchListenerBase.h 2014-07-28 08:51:57 +0000
3+++ include/unity/scopes/SearchListenerBase.h 2014-07-30 21:36:19 +0000
4@@ -19,13 +19,14 @@
5 #ifndef UNITY_SCOPES_SEARCHLISTENERBASE_H
6 #define UNITY_SCOPES_SEARCHLISTENERBASE_H
7
8+#include <unity/scopes/Annotation.h>
9+#include <unity/scopes/CategorisedResult.h>
10+#include <unity/scopes/Category.h>
11+#include <unity/scopes/Department.h>
12+#include <unity/scopes/FilterBase.h>
13 #include <unity/scopes/ListenerBase.h>
14 #include <unity/util/DefinesPtrs.h>
15 #include <unity/util/NonCopyable.h>
16-#include <unity/scopes/Category.h>
17-#include <unity/scopes/Annotation.h>
18-#include <unity/scopes/Department.h>
19-#include <unity/scopes/FilterBase.h>
20
21 #include <string>
22
23@@ -35,9 +36,6 @@
24 namespace scopes
25 {
26
27-class CategorisedResult;
28-class FilterState;
29-
30 namespace experimental
31 {
32 class Annotation;
33
34=== modified file 'src/scopes/internal/ReplyObject.cpp'
35--- src/scopes/internal/ReplyObject.cpp 2014-07-28 09:55:08 +0000
36+++ src/scopes/internal/ReplyObject.cpp 2014-07-30 21:36:19 +0000
37@@ -149,7 +149,6 @@
38 // Only one thread can reach this point, any others were thrown out above.
39
40 reap_item_->destroy();
41- disconnect(); // Disconnect self from middleware, if this hasn't happened yet.
42
43 // Wait until all currently executing calls to push() have completed.
44 unique_lock<mutex> lock(mutex_);
45@@ -175,6 +174,12 @@
46 cerr << "ReplyObject::finished(): unknown exception" << endl;
47 // TODO: log error
48 }
49+
50+ // Disconnect self from middleware, if this hasn't happened yet.
51+ // We do this last because disconnect() can trigger
52+ // the destructor of this instance (if finished() is called
53+ // by the reaper, for example).
54+ disconnect();
55 }
56
57 void ReplyObject::info(OperationInfo const& op_info) noexcept
58
59=== modified file 'test/gtest/scopes/CMakeLists.txt'
60--- test/gtest/scopes/CMakeLists.txt 2014-07-29 09:33:53 +0000
61+++ test/gtest/scopes/CMakeLists.txt 2014-07-30 21:36:19 +0000
62@@ -17,6 +17,7 @@
63 add_subdirectory(RadioButtonsFilter)
64 add_subdirectory(RangeInputFilter)
65 add_subdirectory(RatingFilter)
66+add_subdirectory(ReplyReaper)
67 add_subdirectory(SwitchFilter)
68 add_subdirectory(ValueSliderFilter)
69 add_subdirectory(PreviewWidget)
70
71=== added directory 'test/gtest/scopes/ReplyReaper'
72=== added file 'test/gtest/scopes/ReplyReaper/CMakeLists.txt'
73--- test/gtest/scopes/ReplyReaper/CMakeLists.txt 1970-01-01 00:00:00 +0000
74+++ test/gtest/scopes/ReplyReaper/CMakeLists.txt 2014-07-30 21:36:19 +0000
75@@ -0,0 +1,10 @@
76+configure_file(Registry.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Registry.ini)
77+configure_file(Runtime.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Runtime.ini)
78+configure_file(Zmq.ini.in ${CMAKE_CURRENT_BINARY_DIR}/Zmq.ini)
79+
80+add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}")
81+
82+add_executable(ReplyReaper_test ReplyReaper_test.cpp NoReplyScope.cpp)
83+target_link_libraries(ReplyReaper_test ${TESTLIBS})
84+
85+add_test(ReplyReaper ReplyReaper_test)
86
87=== added file 'test/gtest/scopes/ReplyReaper/NoReplyScope.cpp'
88--- test/gtest/scopes/ReplyReaper/NoReplyScope.cpp 1970-01-01 00:00:00 +0000
89+++ test/gtest/scopes/ReplyReaper/NoReplyScope.cpp 2014-07-30 21:36:19 +0000
90@@ -0,0 +1,61 @@
91+/*
92+ * Copyright (C) 2014 Canonical Ltd
93+ *
94+ * This program is free software: you can redistribute it and/or modify
95+ * it under the terms of the GNU Lesser General Public License version 3 as
96+ * published by the Free Software Foundation.
97+ *
98+ * This program is distributed in the hope that it will be useful,
99+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
100+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
101+ * GNU Lesser General Public License for more details.
102+ *
103+ * You should have received a copy of the GNU Lesser General Public License
104+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
105+ *
106+ * Authored by: Michi Henning <michi.henning@canonical.com>
107+ */
108+
109+#include "NoReplyScope.h"
110+
111+#include <unity/scopes/ScopeBase.h>
112+
113+#include <thread>
114+
115+#include <gtest/gtest.h>
116+
117+using namespace std;
118+using namespace unity::scopes;
119+
120+namespace
121+{
122+
123+class Query : public SearchQueryBase
124+{
125+public:
126+ Query(CannedQuery const& query, SearchMetadata const& metadata)
127+ : SearchQueryBase(query, metadata)
128+ {
129+ }
130+
131+ virtual void run(SearchReplyProxy const&) override
132+ {
133+ this_thread::sleep_for(chrono::seconds(3));
134+ }
135+
136+ virtual void cancelled() override
137+ {
138+ }
139+};
140+
141+} // namespace
142+
143+SearchQueryBase::UPtr NoReplyScope::search(CannedQuery const& query, SearchMetadata const& metadata)
144+{
145+ return SearchQueryBase::UPtr(new Query(query, metadata));
146+}
147+
148+PreviewQueryBase::UPtr NoReplyScope::preview(Result const&, ActionMetadata const&)
149+{
150+ return nullptr; // Not called
151+}
152
153=== added file 'test/gtest/scopes/ReplyReaper/NoReplyScope.h'
154--- test/gtest/scopes/ReplyReaper/NoReplyScope.h 1970-01-01 00:00:00 +0000
155+++ test/gtest/scopes/ReplyReaper/NoReplyScope.h 2014-07-30 21:36:19 +0000
156@@ -0,0 +1,33 @@
157+/*
158+ * Copyright (C) 2014 Canonical Ltd
159+ *
160+ * This program is free software: you can redistribute it and/or modify
161+ * it under the terms of the GNU Lesser General Public License version 3 as
162+ * published by the Free Software Foundation.
163+ *
164+ * This program is distributed in the hope that it will be useful,
165+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
166+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
167+ * GNU Lesser General Public License for more details.
168+ *
169+ * You should have received a copy of the GNU Lesser General Public License
170+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
171+ *
172+ * Authored by: Michi Henning <michi.henning@canonical.com>
173+ */
174+
175+#ifndef TEST_NOREPLYSCOPE_H
176+#define TEST_NOREPLYSCOPE_H
177+
178+#include <unity/scopes/ScopeBase.h>
179+
180+class NoReplyScope : public unity::scopes::ScopeBase
181+{
182+public:
183+ virtual unity::scopes::SearchQueryBase::UPtr search(unity::scopes::CannedQuery const&,
184+ unity::scopes::SearchMetadata const&) override;
185+ virtual unity::scopes::PreviewQueryBase::UPtr preview(unity::scopes::Result const&,
186+ unity::scopes::ActionMetadata const&) override;
187+};
188+
189+#endif
190
191=== added file 'test/gtest/scopes/ReplyReaper/Registry.ini.in'
192--- test/gtest/scopes/ReplyReaper/Registry.ini.in 1970-01-01 00:00:00 +0000
193+++ test/gtest/scopes/ReplyReaper/Registry.ini.in 2014-07-30 21:36:19 +0000
194@@ -0,0 +1,6 @@
195+[Registry]
196+Middleware = Zmq
197+Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
198+Scope.InstallDir = /unused
199+Click.InstallDir = /unused
200+Scoperunner.Path = /unused
201
202=== added file 'test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp'
203--- test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp 1970-01-01 00:00:00 +0000
204+++ test/gtest/scopes/ReplyReaper/ReplyReaper_test.cpp 2014-07-30 21:36:19 +0000
205@@ -0,0 +1,107 @@
206+/*
207+ * Copyright (C) 2014 Canonical Ltd
208+ *
209+ * This program is free software: you can redistribute it and/or modify
210+ * it under the terms of the GNU Lesser General Public License version 3 as
211+ * published by the Free Software Foundation.
212+ *
213+ * This program is distributed in the hope that it will be useful,
214+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
215+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
216+ * GNU Lesser General Public License for more details.
217+ *
218+ * You should have received a copy of the GNU Lesser General Public License
219+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
220+ *
221+ * Authored by: Michi Henning <michi.henning@canonical.com>
222+ */
223+
224+#include <unity/scopes/internal/RegistryObject.h>
225+#include <unity/scopes/internal/RuntimeImpl.h>
226+#include <unity/scopes/internal/ScopeImpl.h>
227+
228+#include <boost/algorithm/string.hpp>
229+#include <gtest/gtest.h>
230+
231+#include "NoReplyScope.h"
232+
233+using namespace std;
234+using namespace unity::scopes;
235+using namespace unity::scopes::internal;
236+
237+class NullReceiver : public SearchListenerBase
238+{
239+public:
240+ NullReceiver()
241+ : query_complete_(false)
242+ {
243+ }
244+
245+ virtual void push(CategorisedResult /* result */) override
246+ {
247+ }
248+
249+ virtual void finished(CompletionDetails const& details) override
250+ {
251+ // Check that finished() was called by the reaper.
252+ EXPECT_EQ(CompletionDetails::Error, details.status()) << details.message();
253+ EXPECT_TRUE(boost::starts_with(details.message(), "No activity on ReplyObject for scope"));
254+ lock_guard<mutex> lock(mutex_);
255+ query_complete_ = true;
256+ cond_.notify_all();
257+ }
258+
259+ void wait_until_finished()
260+ {
261+ unique_lock<mutex> lock(mutex_);
262+ cond_.wait(lock, [this] { return this->query_complete_; });
263+ }
264+
265+private:
266+ bool query_complete_;
267+ mutex mutex_;
268+ condition_variable cond_;
269+};
270+
271+std::shared_ptr<core::posix::SignalTrap>
272+ trap(core::posix::trap_signals_for_all_subsequent_threads({core::posix::Signal::sig_chld}));
273+std::unique_ptr<core::posix::ChildProcess::DeathObserver>
274+ death_observer(core::posix::ChildProcess::DeathObserver::create_once_with_signal_trap(trap));
275+
276+RuntimeImpl::SPtr run_test_registry()
277+{
278+ RuntimeImpl::SPtr runtime = RuntimeImpl::create("TestRegistry", TEST_DIR "/Runtime.ini");
279+ MiddlewareBase::SPtr middleware = runtime->factory()->create("TestRegistry", "Zmq", "Zmq.ini");
280+ RegistryObject::SPtr reg_obj(std::make_shared<RegistryObject>(*death_observer, std::make_shared<Executor>(), middleware));
281+ middleware->add_registry_object("TestRegistry", reg_obj);
282+ return runtime;
283+}
284+
285+void scope_thread(Runtime::SPtr const& rt, string const& runtime_ini_file)
286+{
287+ NoReplyScope scope;
288+ rt->run_scope(&scope, runtime_ini_file, "");
289+}
290+
291+TEST(ReplyReaper, reap)
292+{
293+ auto reg_rt = run_test_registry();
294+
295+ Runtime::SPtr no_reply_rt = move(Runtime::create_scope_runtime("NoReplyScope", TEST_DIR "/Runtime.ini"));
296+ std::thread scope_t(scope_thread, no_reply_rt, TEST_DIR "/Runtime.ini");
297+
298+ // Run a query in the scope. The query will do nothing for 3 seconds,
299+ // but the reaper will reap after at most 2 seconds.
300+ auto rt = internal::RuntimeImpl::create("", TEST_DIR "/Runtime.ini");
301+ auto mw = rt->factory()->create("NoReplyScope", "Zmq", TEST_DIR "/Zmq.ini");
302+ mw->start();
303+ auto proxy = mw->create_scope_proxy("NoReplyScope");
304+ auto scope = internal::ScopeImpl::create(proxy, rt.get(), "NoReplyScope");
305+
306+ auto receiver = make_shared<NullReceiver>();
307+ scope->search("test", SearchMetadata("en", "phone"), receiver);
308+ receiver->wait_until_finished();
309+
310+ no_reply_rt->destroy();
311+ scope_t.join();
312+}
313
314=== added file 'test/gtest/scopes/ReplyReaper/Runtime.ini.in'
315--- test/gtest/scopes/ReplyReaper/Runtime.ini.in 1970-01-01 00:00:00 +0000
316+++ test/gtest/scopes/ReplyReaper/Runtime.ini.in 2014-07-30 21:36:19 +0000
317@@ -0,0 +1,7 @@
318+[Runtime]
319+Registry.Identity = TestRegistry
320+Registry.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Registry.ini
321+Reap.Expiry = 2
322+Reap.Interval = 1
323+Default.Middleware = Zmq
324+Zmq.ConfigFile = @CMAKE_CURRENT_BINARY_DIR@/Zmq.ini
325
326=== added file 'test/gtest/scopes/ReplyReaper/Zmq.ini.in'
327--- test/gtest/scopes/ReplyReaper/Zmq.ini.in 1970-01-01 00:00:00 +0000
328+++ test/gtest/scopes/ReplyReaper/Zmq.ini.in 2014-07-30 21:36:19 +0000
329@@ -0,0 +1,2 @@
330+[Zmq]
331+EndpointDir = /tmp

Subscribers

People subscribed via source and target branches

to all changes: