Mir

Merge lp:~mir-team/mir/fix-1245336 into lp:mir

Proposed by Daniel van Vugt
Status: Rejected
Rejected by: Daniel van Vugt
Proposed branch: lp:~mir-team/mir/fix-1245336
Merge into: lp:mir
Diff against target: 187 lines (+72/-22)
5 files modified
include/test/mir_test_framework/display_server_test_fixture.h (+2/-0)
include/test/mir_test_framework/testing_process_manager.h (+2/-0)
tests/acceptance-tests/test_server_shutdown.cpp (+16/-17)
tests/mir_test_framework/display_server_test_fixture.cpp (+12/-5)
tests/mir_test_framework/testing_process_manager.cpp (+40/-0)
To merge this branch: bzr merge lp:~mir-team/mir/fix-1245336
Reviewer Review Type Date Requested Status
Alan Griffiths Needs Fixing
PS Jenkins bot (community) continuous-integration Approve
Mir development team Pending
Review via email: mp+193009@code.launchpad.net

Commit message

Avoid a race condition that could lead to spurious failures of server
shutdown tests (LP: #1245336)

The race is between the acceptance-tests process and its child server process.
In our signal/abort tests, it's possible the server process may start and
stop so quickly that the parent process doesn't have time to detect the
socket file (before it's correctly cleaned up).

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
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

53 - ASSERT_TRUE(file_exists(server_config.the_socket_file()));

These tests are to prove the server removes the endpoint in various shutdown scenarios. This assert establishes a precondition for the tests to be meaningful and should not be removed.

As discussed on a previous MP the test code in the server should wait until after this file has been detected before raising a fatal signal.

review: Needs Fixing
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Alan,

I've proposed an alternative to address your concern:
   https://code.launchpad.net/~mir-team/mir/fix-1245336.2/+merge/193035
Though I'm slightly more in favour of this one.

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

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'include/test/mir_test_framework/display_server_test_fixture.h'
2--- include/test/mir_test_framework/display_server_test_fixture.h 2013-09-26 15:07:59 +0000
3+++ include/test/mir_test_framework/display_server_test_fixture.h 2013-10-29 08:23:32 +0000
4@@ -60,10 +60,12 @@
5 ~BespokeDisplayServerTestFixture();
6
7 void launch_server_process(TestingServerConfiguration& config);
8+ void launch_failing_server_process(TestingServerConfiguration& config);
9
10 void launch_client_process(TestingClientConfiguration& config);
11
12 bool shutdown_server_process();
13+ Result wait_for_server_death();
14 void kill_client_processes();
15 void terminate_client_processes();
16
17
18=== modified file 'include/test/mir_test_framework/testing_process_manager.h'
19--- include/test/mir_test_framework/testing_process_manager.h 2013-09-25 18:25:11 +0000
20+++ include/test/mir_test_framework/testing_process_manager.h 2013-10-29 08:23:32 +0000
21@@ -51,6 +51,7 @@
22 ~TestingProcessManager();
23
24 void launch_server_process(TestingServerConfiguration& config);
25+ void launch_failing_server_process(TestingServerConfiguration& config);
26 void launch_client_process(TestingClientConfiguration& config,
27 mir::options::Option const& test_options);
28
29@@ -58,6 +59,7 @@
30 void tear_down_server();
31 void tear_down_all();
32 Result shutdown_server_process();
33+ Result wait_server_process();
34 void kill_client_processes();
35 void terminate_client_processes();
36 void run_in_test_process(std::function<void()> const& run_code);
37
38=== modified file 'tests/acceptance-tests/test_server_shutdown.cpp'
39--- tests/acceptance-tests/test_server_shutdown.cpp 2013-10-25 09:01:53 +0000
40+++ tests/acceptance-tests/test_server_shutdown.cpp 2013-10-29 08:23:32 +0000
41@@ -380,17 +380,16 @@
42 };
43
44 ServerConfig server_config;
45- launch_server_process(server_config);
46+ launch_failing_server_process(server_config);
47
48 run_in_test_process([&]
49 {
50- using std::chrono::steady_clock;
51- std::chrono::seconds const limit(2);
52-
53- ASSERT_TRUE(file_exists(server_config.the_socket_file()));
54-
55- // shutdown should fail as the server aborted
56- ASSERT_FALSE(shutdown_server_process());
57+ auto result = wait_for_server_death();
58+
59+ EXPECT_TRUE(result.signalled());
60+
61+ // XXX Somehow the result.signal gets changed to SIGKILL under valgrind
62+ // EXPECT_EQ(SIGABRT, result.signal);
63
64 EXPECT_FALSE(file_exists(server_config.the_socket_file()));
65 });
66@@ -411,18 +410,18 @@
67 int const sig;
68 };
69
70- ServerConfig server_config(GetParam());
71- launch_server_process(server_config);
72+ int const sig = GetParam();
73+ ServerConfig server_config(sig);
74+ launch_failing_server_process(server_config);
75
76 run_in_test_process([&]
77 {
78- using std::chrono::steady_clock;
79- std::chrono::seconds const limit(2);
80-
81- ASSERT_TRUE(file_exists(server_config.the_socket_file()));
82-
83- // shutdown should fail as the server faulted
84- ASSERT_FALSE(shutdown_server_process());
85+ auto result = wait_for_server_death();
86+
87+ EXPECT_TRUE(result.signalled());
88+
89+ // XXX Somehow the result.signal gets changed to SIGKILL under valgrind
90+ // EXPECT_EQ(sig, result.signal);
91
92 EXPECT_FALSE(file_exists(server_config.the_socket_file()));
93 });
94
95=== modified file 'tests/mir_test_framework/display_server_test_fixture.cpp'
96--- tests/mir_test_framework/display_server_test_fixture.cpp 2013-09-26 15:07:59 +0000
97+++ tests/mir_test_framework/display_server_test_fixture.cpp 2013-10-29 08:23:32 +0000
98@@ -60,6 +60,12 @@
99 process_manager.launch_server_process(functor);
100 }
101
102+void BespokeDisplayServerTestFixture::launch_failing_server_process(TestingServerConfiguration& functor)
103+{
104+ test_options = functor.the_options();
105+ process_manager.launch_failing_server_process(functor);
106+}
107+
108 void BespokeDisplayServerTestFixture::launch_client_process(TestingClientConfiguration& config)
109 {
110 process_manager.launch_client_process(config, *test_options);
111@@ -67,12 +73,13 @@
112
113 bool BespokeDisplayServerTestFixture::shutdown_server_process()
114 {
115- // TODO fix problem and remove this frig.
116- // problem: sometimes the server exits normally with status
117- // EXIT_SUCCESS but the test process sees TerminationReason::unknown
118 auto const& result = process_manager.shutdown_server_process();
119- return result.succeeded()
120- || result.reason == TerminationReason::unknown;
121+ return result.succeeded();
122+}
123+
124+mtf::Result BespokeDisplayServerTestFixture::wait_for_server_death()
125+{
126+ return process_manager.wait_server_process();
127 }
128
129 void BespokeDisplayServerTestFixture::terminate_client_processes()
130
131=== modified file 'tests/mir_test_framework/testing_process_manager.cpp'
132--- tests/mir_test_framework/testing_process_manager.cpp 2013-09-30 09:18:00 +0000
133+++ tests/mir_test_framework/testing_process_manager.cpp 2013-10-29 08:23:32 +0000
134@@ -82,6 +82,28 @@
135 }
136 }
137
138+void mtf::TestingProcessManager::launch_failing_server_process(TestingServerConfiguration& config)
139+{
140+ pid_t pid = fork();
141+
142+ if (pid < 0)
143+ {
144+ throw std::runtime_error("Failed to fork process");
145+ }
146+ else if (pid == 0)
147+ {
148+ is_test_process = false;
149+ SCOPED_TRACE("Server");
150+ mir::run_mir(config, [&](mir::DisplayServer&) { config.exec(); });
151+ config.on_exit();
152+ }
153+ else
154+ {
155+ server_process = std::shared_ptr<Process>(new Process(pid));
156+ server_process_was_started = true;
157+ }
158+}
159+
160 /* if set before any calls to the api functions, assigning to this pointer will allow user to
161 * override calls to mir_connect() and mir_connection_release(). This is mostly useful in test scenarios
162 */
163@@ -201,6 +223,24 @@
164 return result;
165 }
166
167+mtf::Result mtf::TestingProcessManager::wait_server_process()
168+{
169+ Result result;
170+
171+ if (server_process)
172+ {
173+ result = server_process->wait_for_termination();
174+ server_process.reset();
175+ }
176+ else
177+ {
178+ result.reason = TerminationReason::child_terminated_normally;
179+ result.exit_code = EXIT_SUCCESS;
180+ }
181+
182+ return result;
183+}
184+
185 void mtf::TestingProcessManager::terminate_client_processes()
186 {
187 if (is_test_process)

Subscribers

People subscribed via source and target branches