Mir

Merge lp:~thomas-voss/mir/fix-fd-sharing into lp:~mir-team/mir/trunk

Proposed by Thomas Voß
Status: Work in progress
Proposed branch: lp:~thomas-voss/mir/fix-fd-sharing
Merge into: lp:~mir-team/mir/trunk
Diff against target: 113 lines (+38/-35)
2 files modified
src/client/rpc/mir_socket_rpc_channel.cpp (+2/-2)
src/server/frontend/socket_messenger.cpp (+36/-33)
To merge this branch: bzr merge lp:~thomas-voss/mir/fix-fd-sharing
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Alan Griffiths Needs Fixing
Daniel van Vugt Needs Information
Chris Halse Rogers Approve
Review via email: mp+180801@code.launchpad.net

Commit message

 * Use correct macros to calculate msg length and alignment when sharing fds.
 * Dispatch via io_service to ensure correct ordering.

Description of the change

 * Use correct macros to calculate msg length and alignment when sharing fds.
 * Dispatch via io_service to ensure correct ordering.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

1. Have we observed any problems with "incorrect" ordering? What's being fixed?

2. Please indent the lambda only 4 spaces in from the dispatch line. That should make it more readable.

review: Needs Information
Revision history for this message
Thomas Voß (thomas-voss) wrote :

> 1. Have we observed any problems with "incorrect" ordering? What's being
> fixed?
>

The issue reported in https://bugs.launchpad.net/mir/+bug/1204939 might be triggered by incorrect ordering of operations on the underlying socket.

> 2. Please indent the lambda only 4 spaces in from the dispatch line. That
> should make it more readable.

fixed.

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

Only the first really needs fixing, but while we're looking at this code...

There's corresponding code in MirSocketRpcChannel::receive_file_descriptors() that also uses "sizeof(struct cmsghdr) + sizeof(int) * n_fds" - the fix should be applied uniformly.

~~~~

77 + int i = 0;
78 + for (auto &fd: fds)
79 + data[i++] = fd;

I guess it is pre-existing, but what's wrong with using std::copy?

std::copy(fds.begin(), fds.end(), data);

~~~~

It is inefficiency rather than a bug, but we're copying a std::vector into the lambda simply to make it available as a data source for further copying.

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

For future safety I would change:
    message->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
to:
    message->cmsg_len = CMSG_LEN(header.msg_controllen);

But it's not that important.

review: Approve
Revision history for this message
Chris Halse Rogers (raof) wrote :

Looks good to me.

Mostly; the lambda's capturing ‘fds’ by value which IIUC will imply another copy of the vector. Although this does mean that we don't need to care about synchronisation.

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

Enough for now. We can worry about the extra copy *if* we measure a performance problem.

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

Is the lambda run in the same thread as the caller?
socket->get_io_service().dispatch(...

If not then it is using fds unsafely unlocked and/or potentially after the object is destroyed.

review: Needs Information
Revision history for this message
Thomas Voß (thomas-voss) wrote :

> Is the lambda run in the same thread as the caller?
> socket->get_io_service().dispatch(...
>

No, that's why the fds are copied into the lambda.

> If not then it is using fds unsafely unlocked and/or potentially after the
> object is destroyed.

It takes a copy of the fds to avoid this issue.

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

> > Is the lambda run in the same thread as the caller?
> > socket->get_io_service().dispatch(...
> >
>
> No, that's why the fds are copied into the lambda.
>
> > If not then it is using fds unsafely unlocked and/or potentially after the
> > object is destroyed.
>
> It takes a copy of the fds to avoid this issue.

Actually, there is an issue here.

That doesn't avoid the issue: the lifetime of the FDs is controlled by the resource_cache. E.g. ~GBMPlatformIPCPackage() closes the FD after the caller returns.

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

Unmerged revisions

986. By Thomas Voß

* Use correct macros in the client-side protobuf communicator, too.
* Replace manual for-loop with std::copy.

985. By Thomas Voß

Fix indent as requested in review.

984. By Thomas Voß

 * Use correct macros to calculate msg length and alignment when sharing fds.
 * Dispatch via io_service to ensure correct ordering.

983. By Alexandros Frantzis

shell: Add infrastructure for emitting and handling session related events.

Approved by PS Jenkins bot, Alan Griffiths.

982. By Alan Griffiths

config: use the DisplayServer to hold ownership of system components, not the DefaultServerConfiguration.

Approved by Alexandros Frantzis, Robert Carr, PS Jenkins bot.

981. By Chris Halse Rogers

Add missing mutex around display config call.

Approved by Alexandros Frantzis, PS Jenkins bot, Daniel van Vugt.

980. By Brandon Schaefer

Clean up config->cards when were are deleting the display config.

Approved by Alexandros Frantzis, Chris Halse Rogers, PS Jenkins bot.

979. By Alan Griffiths

tests: Workaround for test timeout under valgrind. Fixes: https://bugs.launchpad.net/bugs/1212518.

Approved by Daniel van Vugt, Alexandros Frantzis, PS Jenkins bot.

978. By Alan Griffiths

graphics::nested: sketch out some more of the nested mir implementation.

Approved by Alexandros Frantzis, PS Jenkins bot.

977. By Alexandros Frantzis

shell: Notify sessions when the display configuration changes

This patchset implements client notifications for display configuration changes. It also adds a mir_demo_client_display_config example which can be used to test and demo client initiated display configuration changes. Use of the example uncovered some issues that are also fixed by this patchset (see individual commits for more info).

Approved by PS Jenkins bot, Alan Griffiths.

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-08-08 02:34:31 +0000
3+++ src/client/rpc/mir_socket_rpc_channel.cpp 2013-08-19 09:19:06 +0000
4@@ -176,7 +176,7 @@
5
6 // Allocate space for control message
7 auto n_fds = fds.size();
8- std::vector<char> control(sizeof(struct cmsghdr) + sizeof(int) * n_fds);
9+ std::vector<char> control(CMSG_SPACE(sizeof(int) * n_fds));
10
11 // Message to send
12 struct msghdr header;
13@@ -190,7 +190,7 @@
14
15 // Control message contains file descriptors
16 struct cmsghdr *message = CMSG_FIRSTHDR(&header);
17- message->cmsg_len = header.msg_controllen;
18+ message->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
19 message->cmsg_level = SOL_SOCKET;
20 message->cmsg_type = SCM_RIGHTS;
21
22
23=== modified file 'src/server/frontend/socket_messenger.cpp'
24--- src/server/frontend/socket_messenger.cpp 2013-08-01 09:55:02 +0000
25+++ src/server/frontend/socket_messenger.cpp 2013-08-19 09:19:06 +0000
26@@ -33,9 +33,9 @@
27 {
28 struct ucred cr;
29 socklen_t cl = sizeof(cr);
30-
31+
32 auto status = getsockopt(socket->native_handle(), SOL_SOCKET, SO_PEERCRED, &cr, &cl);
33-
34+
35 if (status)
36 BOOST_THROW_EXCEPTION(std::runtime_error("Failed to query client socket credentials"));
37 return cr.pid;
38@@ -65,36 +65,39 @@
39 auto n_fds = fds.size();
40 if (n_fds > 0)
41 {
42- // We send dummy data
43- struct iovec iov;
44- char dummy_iov_data = 'M';
45- iov.iov_base = &dummy_iov_data;
46- iov.iov_len = 1;
47-
48- // Allocate space for control message
49- std::vector<char> control(sizeof(struct cmsghdr) + sizeof(int) * n_fds);
50-
51- // Message to send
52- struct msghdr header;
53- header.msg_name = NULL;
54- header.msg_namelen = 0;
55- header.msg_iov = &iov;
56- header.msg_iovlen = 1;
57- header.msg_controllen = control.size();
58- header.msg_control = control.data();
59- header.msg_flags = 0;
60-
61- // Control message contains file descriptors
62- struct cmsghdr *message = CMSG_FIRSTHDR(&header);
63- message->cmsg_len = header.msg_controllen;
64- message->cmsg_level = SOL_SOCKET;
65- message->cmsg_type = SCM_RIGHTS;
66- int *data = (int *)CMSG_DATA(message);
67- int i = 0;
68- for (auto &fd: fds)
69- data[i++] = fd;
70-
71- sendmsg(socket->native_handle(), &header, 0);
72+ socket->get_io_service().dispatch(
73+ [this, fds, n_fds]()
74+ {
75+ // We send dummy data
76+ struct iovec iov;
77+ char dummy_iov_data = 'M';
78+ iov.iov_base = &dummy_iov_data;
79+ iov.iov_len = 1;
80+
81+ // Allocate space for control message
82+ std::vector<char> control(CMSG_SPACE(sizeof(int) * n_fds));
83+ // Message to send
84+ struct msghdr header;
85+ header.msg_name = NULL;
86+ header.msg_namelen = 0;
87+ header.msg_iov = &iov;
88+ header.msg_iovlen = 1;
89+ header.msg_controllen = control.size();
90+ header.msg_control = control.data();
91+ header.msg_flags = 0;
92+
93+ // Control message contains file descriptors
94+ struct cmsghdr *message = CMSG_FIRSTHDR(&header);
95+ message->cmsg_len = CMSG_LEN(sizeof(int) * n_fds);
96+ message->cmsg_level = SOL_SOCKET;
97+ message->cmsg_type = SCM_RIGHTS;
98+ std::copy(
99+ fds.begin(),
100+ fds.end(),
101+ reinterpret_cast<int*>(CMSG_DATA(message)));
102+
103+ sendmsg(socket->native_handle(), &header, 0);
104+ });
105 }
106 }
107
108@@ -106,4 +109,4 @@
109 buffer,
110 boost::asio::transfer_exactly(size),
111 handler);
112-}
113+}

Subscribers

People subscribed via source and target branches