Mir

Merge lp:~raof/mir/threads-and-madness into lp:~mir-team/mir/trunk

Proposed by Chris Halse Rogers
Status: Merged
Approved by: Robert Ancell
Approved revision: no longer in the source branch.
Merged at revision: 841
Proposed branch: lp:~raof/mir/threads-and-madness
Merge into: lp:~mir-team/mir/trunk
Diff against target: 144 lines (+112/-0)
2 files modified
src/client/rpc/mir_socket_rpc_channel.cpp (+23/-0)
tests/acceptance-tests/test_client_library.cpp (+89/-0)
To merge this branch: bzr merge lp:~raof/mir/threads-and-madness
Reviewer Review Type Date Requested Status
Thomas Voß (community) Approve
PS Jenkins bot (community) continuous-integration Approve
Robert Ancell Approve
Review via email: mp+174098@code.launchpad.net

Commit message

Make libmirclient not aggressively signal-unsafe by blocking signals on our
IO thread.

Fixes infinite loop in XMir (LP: #1199319)

Description of the change

Make libmirclient not aggressively signal-unsafe by blocking signals on our
IO thread.

Fixes: (LP: #1199319)

To post a comment you must log in.
Revision history for this message
Robert Ancell (robert-ancell) wrote :

I don't understand the details but looks sane. Well, except for the commit comment that is...

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Thomas Voß (thomas-voss) wrote :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/client/rpc/mir_socket_rpc_channel.cpp'
2--- src/client/rpc/mir_socket_rpc_channel.cpp 2013-07-08 04:51:27 +0000
3+++ src/client/rpc/mir_socket_rpc_channel.cpp 2013-07-11 03:13:31 +0000
4@@ -26,10 +26,16 @@
5 #include "mir_protobuf.pb.h" // For Buffer frig
6 #include "mir_protobuf_wire.pb.h"
7
8+#include <boost/exception/errinfo_errno.hpp>
9+#include <boost/throw_exception.hpp>
10+
11 #include <boost/bind.hpp>
12 #include <cstring>
13 #include <sstream>
14
15+#include <pthread.h>
16+#include <signal.h>
17+
18 namespace mclr = mir::client::rpc;
19
20 mclr::MirSocketRpcChannel::MirSocketRpcChannel(
21@@ -46,8 +52,25 @@
22
23 auto run_io_service = boost::bind(&boost::asio::io_service::run, &io_service);
24
25+ // Our IO threads must not recieve any signals
26+ sigset_t all_signals;
27+ sigfillset(&all_signals);
28+ sigset_t old_mask;
29+ int error;
30+ if ((error = pthread_sigmask(SIG_BLOCK, &all_signals, &old_mask)))
31+ BOOST_THROW_EXCEPTION(
32+ boost::enable_error_info(
33+ std::runtime_error("Failed to block signals on IO thread")) << boost::errinfo_errno(error));
34+
35+
36 io_service_thread = std::move(std::thread(run_io_service));
37
38+ // Restore previous signals.
39+ if ((error = pthread_sigmask(SIG_SETMASK, &old_mask, NULL)))
40+ BOOST_THROW_EXCEPTION(
41+ boost::enable_error_info(
42+ std::runtime_error("Failed to restore signal mask")) << boost::errinfo_errno(error));
43+
44 boost::asio::async_read(
45 socket,
46 boost::asio::buffer(header_bytes),
47
48=== modified file 'tests/acceptance-tests/test_client_library.cpp'
49--- tests/acceptance-tests/test_client_library.cpp 2013-06-28 10:42:44 +0000
50+++ tests/acceptance-tests/test_client_library.cpp 2013-07-11 03:13:31 +0000
51@@ -773,4 +773,93 @@
52
53 launch_client_process(client_config);
54 }
55+
56+bool signalled;
57+static void SIGIO_handler(int /*signo*/)
58+{
59+ signalled = true;
60+}
61+
62+TEST_F(DefaultDisplayServerTestFixture, ClientLibraryThreadsHandleNoSignals)
63+{
64+ struct ClientConfig : ClientConfigCommon
65+ {
66+ void exec()
67+ {
68+ signalled = false;
69+
70+ sigset_t sigset;
71+ sigemptyset(&sigset);
72+ struct sigaction act;
73+ act.sa_handler = &SIGIO_handler;
74+ act.sa_mask = sigset;
75+ act.sa_flags = 0;
76+ act.sa_restorer = nullptr;
77+ if (sigaction(SIGIO, &act, NULL))
78+ FAIL() << "Failed to set SIGIO action";
79+
80+ MirConnection* conn = NULL;
81+ conn = mir_connect_sync(mir_test_socket, __PRETTY_FUNCTION__);
82+
83+ sigaddset(&sigset, SIGIO);
84+ pthread_sigmask(SIG_BLOCK, &sigset, NULL);
85+
86+ // SIGIO should be blocked
87+ if (kill(getpid(), SIGIO))
88+ FAIL() << "Failed to send SIGIO signal";
89+
90+ // Make a roundtrip to the server to ensure the SIGIO has time to be handled
91+ MirSurfaceParameters const request_params =
92+ {
93+ __PRETTY_FUNCTION__,
94+ 640, 480,
95+ mir_pixel_format_abgr_8888,
96+ mir_buffer_usage_software
97+ };
98+
99+ surface = mir_connection_create_surface_sync(conn, &request_params);
100+
101+ mir_connection_release(conn);
102+
103+ EXPECT_FALSE(signalled);
104+ }
105+ } client_config;
106+
107+ launch_client_process(client_config);
108+}
109+
110+TEST_F(DefaultDisplayServerTestFixture, ClientLibraryDoesNotInterfereWithClientSignalHandling)
111+{
112+ struct ClientConfig : ClientConfigCommon
113+ {
114+ void exec()
115+ {
116+ signalled = false;
117+
118+ sigset_t sigset;
119+ sigemptyset(&sigset);
120+ struct sigaction act;
121+ act.sa_handler = &SIGIO_handler;
122+ act.sa_mask = sigset;
123+ act.sa_flags = 0;
124+ act.sa_restorer = nullptr;
125+ if (sigaction(SIGIO, &act, NULL))
126+ FAIL() << "Failed to set SIGIO action";
127+
128+ MirConnection* conn = NULL;
129+ conn = mir_connect_sync(mir_test_socket, __PRETTY_FUNCTION__);
130+
131+ // We should receieve SIGIO
132+ if (kill(getpid(), SIGIO))
133+ FAIL() << "Failed to send SIGIO signal";
134+
135+ mir_connection_release(conn);
136+
137+ EXPECT_TRUE(signalled);
138+ }
139+ } client_config;
140+
141+ launch_client_process(client_config);
142+}
143+
144 }

Subscribers

People subscribed via source and target branches