Mir

Merge lp:~alan-griffiths/mir/client-dies-without-server into lp:mir

Proposed by Alan Griffiths
Status: Merged
Approved by: Alexandros Frantzis
Approved revision: 1095
Merged at revision: 1097
Proposed branch: lp:~alan-griffiths/mir/client-dies-without-server
Merge into: lp:mir
Diff against target: 446 lines (+151/-78)
14 files modified
include/test/mir_test_doubles/mock_rpc_report.h (+2/-0)
src/client/logging/rpc_report.cpp (+9/-0)
src/client/logging/rpc_report.h (+17/-15)
src/client/lttng/rpc_report.cpp (+4/-0)
src/client/lttng/rpc_report.h (+17/-15)
src/client/mir_connection.cpp (+20/-4)
src/client/rpc/mir_basic_rpc_channel.cpp (+14/-0)
src/client/rpc/mir_basic_rpc_channel.h (+2/-0)
src/client/rpc/mir_socket_rpc_channel.cpp (+38/-29)
src/client/rpc/null_rpc_report.cpp (+4/-0)
src/client/rpc/null_rpc_report.h (+17/-15)
src/client/rpc/rpc_report.h (+2/-0)
tests/mir_test_framework/testing_process_manager.cpp (+2/-0)
tests/unit-tests/client/test_client_mir_surface.cpp (+3/-0)
To merge this branch: bzr merge lp:~alan-griffiths/mir/client-dies-without-server
Reviewer Review Type Date Requested Status
Alexandros Frantzis (community) Approve
Robert Carr (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Kevin DuBois (community) Approve
Alan Griffiths Abstain
Review via email: mp+187797@code.launchpad.net

Commit message

client: Clean up client side error handling and suicide if connection fails

Description of the change

client: Clean up client side error handling and suicide if connection fails

Three bits of cleanup:

1. No longer swallowing errors on the connection
2. Trapping errors propagating from io_service::run()
3. Reporting and acting on a connection failure

The latter is admittedly inflexible, but I'll address that in a follow-up. The current approach ensures that any client gets a SIGTERM and can exit tidily instead of hanging within the mir client library.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

The following tests FAILED:
   4 - memcheck(acceptance-tests.ClientPidTestFixture.*) (Failed)

I think this is an existing intermittent test failure - I can't reproduce and it is mentioned in bug #1231341

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

> The following tests FAILED:
> 4 - memcheck(acceptance-tests.ClientPidTestFixture.*) (Failed)
>
> I think this is an existing intermittent test failure - I can't reproduce and
> it is mentioned in bug #1231341

Actually, MP seems to make this error a bit more common (maybe *10). I'll investigate tomorrow, but leave the MP for review.

review: Needs Fixing
Revision history for this message
Kevin DuBois (kdub) wrote :

I suppose sigterm is an ok temporary solution (and better than hanging)... still problematic though, because the io service has died, a properly written client would try to release its surfaces and disconnect on SIGTERM. A client can't tell whether the signal came from a mir library or something like "kill -SIGTERM". What's final plan for informing the client the server died? callback in the api maybe?

review: Needs Information
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> I suppose sigterm is an ok temporary solution (and better than hanging)...
> still problematic though, because the io service has died, a properly written
> client would try to release its surfaces and disconnect on SIGTERM. A client
> can't tell whether the signal came from a mir library or something like "kill
> -SIGTERM".

Yes, and those calls now fail gracefully. (C.f. 153 etc.)

> What's final plan for informing the client the server died?
> callback in the api maybe?

Adding a lifecycle notification callback that the server connection died.

1092. By Alan Griffiths

merge lp:~mir-team/mir/development-branch

1093. By Alan Griffiths

Fix some of the failure modes

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> > The following tests FAILED:
> > 4 - memcheck(acceptance-tests.ClientPidTestFixture.*) (Failed)
> >
> > I think this is an existing intermittent test failure - I can't reproduce
> and
> > it is mentioned in bug #1231341
>
> Actually, MP seems to make this error a bit more common (maybe *10). I'll
> investigate tomorrow, but leave the MP for review.

I've chased down some of what is happening and got this branch back on a par with trunk.

I'm going sort this properly as bug 1231902 - but as it's an existing problem I don't think this need block this branch.

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

well, looks okay to me then

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

This:
    kill(getpid(), SIGTERM);
should generally be:
    raise(SIGTERM);
Though either is scary.

1094. By Alan Griffiths

merge lp:~mir-team/mir/development-branch

1095. By Alan Griffiths

Daniel's suggestion

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

OK until we implement the lifetime callback approach and works as expected.

I think it's worth having an acceptance test for this now (i.e., that clients die when the server dies), since even with the lifetime callback approach I expect this to be the default behavior.

review: Needs Fixing
Revision history for this message
Robert Carr (robertcarr) wrote :

Looks ok to me. I agree an acceptance test is good to have though.

review: Approve
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

> OK until we implement the lifetime callback approach and works as expected.
>
> I think it's worth having an acceptance test for this now (i.e., that clients
> die when the server dies), since even with the lifetime callback approach I
> expect this to be the default behavior.

I don't really want to write an acceptance test for the SIGTERM behavior as I plan to replace it with something less ugly.

If I promise to to MP a test in the next iteration can we land this?

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> If I promise to to MP a test in the next iteration can we land this?

Sounds good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/test/mir_test_doubles/mock_rpc_report.h'
2--- include/test/mir_test_doubles/mock_rpc_report.h 2013-05-29 12:04:04 +0000
3+++ include/test/mir_test_doubles/mock_rpc_report.h 2013-09-30 09:20:28 +0000
4@@ -69,6 +69,8 @@
5 MOCK_METHOD2(file_descriptors_received,
6 void(google::protobuf::Message const&,
7 std::vector<int32_t> const&));
8+
9+ MOCK_METHOD1(connection_failure, void (std::exception const&));
10 };
11
12
13
14=== modified file 'src/client/logging/rpc_report.cpp'
15--- src/client/logging/rpc_report.cpp 2013-06-03 08:14:01 +0000
16+++ src/client/logging/rpc_report.cpp 2013-09-30 09:20:28 +0000
17@@ -22,6 +22,7 @@
18
19 #include "mir_protobuf_wire.pb.h"
20
21+#include <boost/exception/diagnostic_information.hpp>
22 #include <sstream>
23
24 namespace ml = mir::logging;
25@@ -155,3 +156,11 @@
26
27 logger->log<ml::Logger::debug>(ss.str(), component);
28 }
29+
30+void mcll::RpcReport::connection_failure(std::exception const& x)
31+{
32+ std::stringstream ss;
33+ ss << "Connection failure: " << boost::diagnostic_information(x) << std::endl;
34+
35+ logger->log<ml::Logger::warning>(ss.str(), component);
36+}
37
38=== modified file 'src/client/logging/rpc_report.h'
39--- src/client/logging/rpc_report.h 2013-06-03 08:14:01 +0000
40+++ src/client/logging/rpc_report.h 2013-09-30 09:20:28 +0000
41@@ -41,26 +41,28 @@
42 public:
43 RpcReport(std::shared_ptr<mir::logging::Logger> const& logger);
44
45- void invocation_requested(mir::protobuf::wire::Invocation const& invocation);
46- void invocation_succeeded(mir::protobuf::wire::Invocation const& invocation);
47+ void invocation_requested(mir::protobuf::wire::Invocation const& invocation) override;
48+ void invocation_succeeded(mir::protobuf::wire::Invocation const& invocation) override;
49 void invocation_failed(mir::protobuf::wire::Invocation const& invocation,
50- boost::system::error_code const& error);
51-
52- void header_receipt_failed(boost::system::error_code const& error);
53- void result_receipt_succeeded(mir::protobuf::wire::Result const& result);
54- void result_receipt_failed(std::exception const& ex);
55-
56- void event_parsing_succeeded(MirEvent const& event);
57- void event_parsing_failed(mir::protobuf::Event const& event);
58-
59- void orphaned_result(mir::protobuf::wire::Result const& result);
60- void complete_response(mir::protobuf::wire::Result const& result);
61+ boost::system::error_code const& error) override;
62+
63+ void header_receipt_failed(boost::system::error_code const& error) override;
64+ void result_receipt_succeeded(mir::protobuf::wire::Result const& result) override;
65+ void result_receipt_failed(std::exception const& ex) override;
66+
67+ void event_parsing_succeeded(MirEvent const& event) override;
68+ void event_parsing_failed(mir::protobuf::Event const& event) override;
69+
70+ void orphaned_result(mir::protobuf::wire::Result const& result) override;
71+ void complete_response(mir::protobuf::wire::Result const& result) override;
72
73 void result_processing_failed(mir::protobuf::wire::Result const& result,
74- std::exception const& ex);
75+ std::exception const& ex) override;
76
77 void file_descriptors_received(google::protobuf::Message const& response,
78- std::vector<int32_t> const& fds);
79+ std::vector<int32_t> const& fds) override;
80+
81+ void connection_failure(std::exception const& ex) override;
82
83 private:
84 std::shared_ptr<mir::logging::Logger> const logger;
85
86=== modified file 'src/client/lttng/rpc_report.cpp'
87--- src/client/lttng/rpc_report.cpp 2013-06-03 12:15:45 +0000
88+++ src/client/lttng/rpc_report.cpp 2013-09-30 09:20:28 +0000
89@@ -99,3 +99,7 @@
90 mir_tracepoint(mir_client_rpc, file_descriptors_received,
91 fds.data(), fds.size());
92 }
93+
94+void mcl::lttng::RpcReport::connection_failure(std::exception const& /*ex*/)
95+{
96+}
97
98=== modified file 'src/client/lttng/rpc_report.h'
99--- src/client/lttng/rpc_report.h 2013-06-03 12:15:45 +0000
100+++ src/client/lttng/rpc_report.h 2013-09-30 09:20:28 +0000
101@@ -32,26 +32,28 @@
102 class RpcReport : public rpc::RpcReport
103 {
104 public:
105- void invocation_requested(mir::protobuf::wire::Invocation const& invocation);
106- void invocation_succeeded(mir::protobuf::wire::Invocation const& invocation);
107+ void invocation_requested(mir::protobuf::wire::Invocation const& invocation) override;
108+ void invocation_succeeded(mir::protobuf::wire::Invocation const& invocation) override;
109 void invocation_failed(mir::protobuf::wire::Invocation const& invocation,
110- boost::system::error_code const& error);
111-
112- void header_receipt_failed(boost::system::error_code const& error);
113- void result_receipt_succeeded(mir::protobuf::wire::Result const& result);
114- void result_receipt_failed(std::exception const& ex);
115-
116- void event_parsing_succeeded(MirEvent const& event);
117- void event_parsing_failed(mir::protobuf::Event const& event);
118-
119- void orphaned_result(mir::protobuf::wire::Result const& result);
120- void complete_response(mir::protobuf::wire::Result const& result);
121+ boost::system::error_code const& error) override;
122+
123+ void header_receipt_failed(boost::system::error_code const& error) override;
124+ void result_receipt_succeeded(mir::protobuf::wire::Result const& result) override;
125+ void result_receipt_failed(std::exception const& ex) override;
126+
127+ void event_parsing_succeeded(MirEvent const& event) override;
128+ void event_parsing_failed(mir::protobuf::Event const& event) override;
129+
130+ void orphaned_result(mir::protobuf::wire::Result const& result) override;
131+ void complete_response(mir::protobuf::wire::Result const& result) override;
132
133 void result_processing_failed(mir::protobuf::wire::Result const& result,
134- std::exception const& ex);
135+ std::exception const& ex) override;
136
137 void file_descriptors_received(google::protobuf::Message const& response,
138- std::vector<int32_t> const& fds);
139+ std::vector<int32_t> const& fds) override;
140+
141+ void connection_failure(std::exception const& ex) override;
142
143 private:
144 ClientTracepointProvider tp_provider;
145
146=== modified file 'src/client/mir_connection.cpp'
147--- src/client/mir_connection.cpp 2013-09-23 13:37:44 +0000
148+++ src/client/mir_connection.cpp 2013-09-30 09:20:28 +0000
149@@ -179,13 +179,22 @@
150
151 SurfaceRelease surf_release{surface, new_wait_handle, callback, context};
152
153- mir::protobuf::SurfaceId message;
154- message.set_value(surface->id());
155- server.release_surface(0, &message, &void_response,
156- gp::NewCallback(this, &MirConnection::released, surf_release));
157+ try
158+ {
159+ mir::protobuf::SurfaceId message;
160+ message.set_value(surface->id());
161+ server.release_surface(0, &message, &void_response,
162+ gp::NewCallback(this, &MirConnection::released, surf_release));
163+ }
164+ catch (std::exception const& x)
165+ {
166+ set_error_message(std::string("release_surface: ") + x.what());
167+ released(surf_release);
168+ }
169
170 std::lock_guard<std::mutex> rel_lock(release_wait_handle_guard);
171 release_wait_handles.push_back(new_wait_handle);
172+
173 return new_wait_handle;
174 }
175
176@@ -194,6 +203,13 @@
177 {
178 std::lock_guard<std::recursive_mutex> lock(mutex);
179
180+ if (!connect_result.has_platform() || !connect_result.has_display_configuration())
181+ {
182+ if (!connect_result.has_error())
183+ {
184+ set_error_message("Connect failed");
185+ }
186+ }
187 /*
188 * We need to create the client platform after the connection has been
189 * established, to ensure that the client platform has access to all
190
191=== modified file 'src/client/rpc/mir_basic_rpc_channel.cpp'
192--- src/client/rpc/mir_basic_rpc_channel.cpp 2013-08-29 03:48:16 +0000
193+++ src/client/rpc/mir_basic_rpc_channel.cpp 2013-09-30 09:20:28 +0000
194@@ -70,6 +70,20 @@
195 }
196 }
197
198+void mclrd::PendingCallCache::force_completion()
199+{
200+ std::unique_lock<std::mutex> lock(mutex);
201+ for (auto& call : pending_calls)
202+ {
203+ auto& completion = call.second;
204+ completion.complete->Run();
205+ }
206+
207+ pending_calls.erase(pending_calls.begin(), pending_calls.end());
208+}
209+
210+
211+
212 bool mclrd::PendingCallCache::empty() const
213 {
214 std::unique_lock<std::mutex> lock(mutex);
215
216=== modified file 'src/client/rpc/mir_basic_rpc_channel.h'
217--- src/client/rpc/mir_basic_rpc_channel.h 2013-08-28 03:41:48 +0000
218+++ src/client/rpc/mir_basic_rpc_channel.h 2013-09-30 09:20:28 +0000
219@@ -62,6 +62,8 @@
220
221 void complete_response(mir::protobuf::wire::Result& result);
222
223+ void force_completion();
224+
225 bool empty() const;
226
227 private:
228
229=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
230--- src/client/rpc/mir_socket_rpc_channel.cpp 2013-09-20 18:42:07 +0000
231+++ src/client/rpc/mir_socket_rpc_channel.cpp 2013-09-30 09:20:28 +0000
232@@ -84,32 +84,38 @@
233
234 void mclr::MirSocketRpcChannel::init()
235 {
236- auto run_io_service = boost::bind(&boost::asio::io_service::run, &io_service);
237-
238- // Our IO threads must not recieve any signals
239- sigset_t all_signals;
240- sigfillset(&all_signals);
241- sigset_t old_mask;
242- int error;
243- if ((error = pthread_sigmask(SIG_BLOCK, &all_signals, &old_mask)))
244- BOOST_THROW_EXCEPTION(
245- boost::enable_error_info(
246- std::runtime_error("Failed to block signals on IO thread")) << boost::errinfo_errno(error));
247-
248- io_service_thread = std::thread(run_io_service);
249-
250- // Restore previous signals.
251- if ((error = pthread_sigmask(SIG_SETMASK, &old_mask, NULL)))
252- BOOST_THROW_EXCEPTION(
253- boost::enable_error_info(
254- std::runtime_error("Failed to restore signal mask")) << boost::errinfo_errno(error));
255-
256- boost::asio::async_read(
257- socket,
258- boost::asio::buffer(header_bytes),
259- boost::asio::transfer_exactly(sizeof header_bytes),
260- boost::bind(&MirSocketRpcChannel::on_header_read, this,
261- boost::asio::placeholders::error));
262+ io_service_thread = std::thread([&]
263+ {
264+ // Our IO threads must not receive any signals
265+ sigset_t all_signals;
266+ sigfillset(&all_signals);
267+
268+ if (auto error = pthread_sigmask(SIG_BLOCK, &all_signals, NULL))
269+ BOOST_THROW_EXCEPTION(
270+ boost::enable_error_info(
271+ std::runtime_error("Failed to block signals on IO thread")) << boost::errinfo_errno(error));
272+
273+ boost::asio::async_read(
274+ socket,
275+ boost::asio::buffer(header_bytes),
276+ boost::asio::transfer_exactly(sizeof header_bytes),
277+ boost::bind(&MirSocketRpcChannel::on_header_read, this,
278+ boost::asio::placeholders::error));
279+
280+ try
281+ {
282+ io_service.run();
283+ }
284+ catch (std::exception const& x)
285+ {
286+ rpc_report->connection_failure(x);
287+
288+ // TODO enable configuring the kill mechanism
289+ io_service.stop();
290+ raise(SIGTERM);
291+ pending_calls.force_completion();
292+ }
293+ });
294 }
295
296 mclr::MirSocketRpcChannel::~MirSocketRpcChannel()
297@@ -268,6 +274,7 @@
298 body.SerializeToArray(send_buffer.data() + sizeof header_bytes, size);
299
300 boost::system::error_code error;
301+
302 boost::asio::write(
303 socket,
304 boost::asio::buffer(send_buffer),
305@@ -276,8 +283,7 @@
306 if (error)
307 {
308 rpc_report->invocation_failed(invocation, error);
309-
310- BOOST_THROW_EXCEPTION(std::runtime_error("Failed to send message to server"));
311+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to send message to server: " + error.message()));
312 }
313 else
314 rpc_report->invocation_succeeded(invocation);
315@@ -292,6 +298,7 @@
316 if (!pending_calls.empty() || error != boost::asio::error::eof)
317 {
318 rpc_report->header_receipt_failed(error);
319+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to read message header: " + error.message()));
320 }
321
322 return;
323@@ -322,6 +329,7 @@
324 catch (std::exception const& x)
325 {
326 rpc_report->result_receipt_failed(x);
327+ throw;
328 }
329
330 try
331@@ -339,6 +347,7 @@
332 catch (std::exception const& x)
333 {
334 rpc_report->result_processing_failed(result, x);
335+ // Eat this exception as it doesn't affect rpc
336 }
337 }
338
339@@ -406,7 +415,7 @@
340 boost::asio::read(socket, message, boost::asio::transfer_exactly(body_size), error);
341 if (error)
342 {
343- BOOST_THROW_EXCEPTION(std::runtime_error(error.message()));
344+ BOOST_THROW_EXCEPTION(std::runtime_error("Failed to read message body: " + error.message()));
345 }
346
347 std::istream in(&message);
348
349=== modified file 'src/client/rpc/null_rpc_report.cpp'
350--- src/client/rpc/null_rpc_report.cpp 2013-05-29 12:04:04 +0000
351+++ src/client/rpc/null_rpc_report.cpp 2013-09-30 09:20:28 +0000
352@@ -84,3 +84,7 @@
353 std::vector<int32_t> const& /*fds*/)
354 {
355 }
356+
357+void mclr::NullRpcReport::connection_failure(std::exception const& /*ex*/)
358+{
359+}
360
361=== modified file 'src/client/rpc/null_rpc_report.h'
362--- src/client/rpc/null_rpc_report.h 2013-05-29 12:04:04 +0000
363+++ src/client/rpc/null_rpc_report.h 2013-09-30 09:20:28 +0000
364@@ -31,26 +31,28 @@
365 class NullRpcReport : public RpcReport
366 {
367 public:
368- void invocation_requested(mir::protobuf::wire::Invocation const& invocation);
369- void invocation_succeeded(mir::protobuf::wire::Invocation const& invocation);
370+ void invocation_requested(mir::protobuf::wire::Invocation const& invocation) override;
371+ void invocation_succeeded(mir::protobuf::wire::Invocation const& invocation) override;
372 void invocation_failed(mir::protobuf::wire::Invocation const& invocation,
373- boost::system::error_code const& error);
374-
375- void header_receipt_failed(boost::system::error_code const& error);
376- void result_receipt_succeeded(mir::protobuf::wire::Result const& result);
377- void result_receipt_failed(std::exception const& ex);
378-
379- void event_parsing_succeeded(MirEvent const& event);
380- void event_parsing_failed(mir::protobuf::Event const& event);
381-
382- void orphaned_result(mir::protobuf::wire::Result const& result);
383- void complete_response(mir::protobuf::wire::Result const& result);
384+ boost::system::error_code const& error) override;
385+
386+ void header_receipt_failed(boost::system::error_code const& error) override;
387+ void result_receipt_succeeded(mir::protobuf::wire::Result const& result) override;
388+ void result_receipt_failed(std::exception const& ex) override;
389+
390+ void event_parsing_succeeded(MirEvent const& event) override;
391+ void event_parsing_failed(mir::protobuf::Event const& event) override;
392+
393+ void orphaned_result(mir::protobuf::wire::Result const& result) override;
394+ void complete_response(mir::protobuf::wire::Result const& result) override;
395
396 void result_processing_failed(mir::protobuf::wire::Result const& result,
397- std::exception const& ex);
398+ std::exception const& ex) override;
399
400 void file_descriptors_received(google::protobuf::Message const& response,
401- std::vector<int32_t> const& fds);
402+ std::vector<int32_t> const& fds) override;
403+
404+ void connection_failure(std::exception const& ex) override;
405 };
406
407 }
408
409=== modified file 'src/client/rpc/rpc_report.h'
410--- src/client/rpc/rpc_report.h 2013-05-29 12:04:04 +0000
411+++ src/client/rpc/rpc_report.h 2013-09-30 09:20:28 +0000
412@@ -66,6 +66,8 @@
413 virtual void file_descriptors_received(google::protobuf::Message const& response,
414 std::vector<int32_t> const& fds) = 0;
415
416+ virtual void connection_failure(std::exception const& ex) = 0;
417+
418 protected:
419 RpcReport() = default;
420 RpcReport(RpcReport const&) = delete;
421
422=== modified file 'tests/mir_test_framework/testing_process_manager.cpp'
423--- tests/mir_test_framework/testing_process_manager.cpp 2013-09-25 19:27:16 +0000
424+++ tests/mir_test_framework/testing_process_manager.cpp 2013-09-30 09:20:28 +0000
425@@ -45,6 +45,8 @@
426 is_test_process(true),
427 server_process_was_started(false)
428 {
429+ // In case an earlier test left a stray file
430+ std::remove(test_socket_file().c_str());
431 }
432
433 mtf::TestingProcessManager::~TestingProcessManager()
434
435=== modified file 'tests/unit-tests/client/test_client_mir_surface.cpp'
436--- tests/unit-tests/client/test_client_mir_surface.cpp 2013-09-24 11:07:53 +0000
437+++ tests/unit-tests/client/test_client_mir_surface.cpp 2013-09-30 09:20:28 +0000
438@@ -292,6 +292,9 @@
439 {
440 void SetUp()
441 {
442+ // In case an earlier test left a stray file
443+ std::remove("./test_socket_surface");
444+
445 mock_server_tool = std::make_shared<mt::MockServerPackageGenerator>();
446 test_server = std::make_shared<mt::TestProtobufServer>("./test_socket_surface", mock_server_tool);
447

Subscribers

People subscribed via source and target branches