Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1118)

Side by Side Diff: sandbox/win/src/sharedmem_ipc_client.cc

Issue 1851213002: Remove sandbox on Windows. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nacl compile issues Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sandbox/win/src/sharedmem_ipc_client.h ('k') | sandbox/win/src/sharedmem_ipc_server.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <stddef.h>
6 #include <string.h>
7
8 #include "base/logging.h"
9 #include "sandbox/win/src/crosscall_client.h"
10 #include "sandbox/win/src/crosscall_params.h"
11 #include "sandbox/win/src/sandbox.h"
12 #include "sandbox/win/src/sharedmem_ipc_client.h"
13
14 namespace sandbox {
15
16 // Get the base of the data buffer of the channel; this is where the input
17 // parameters get serialized. Since they get serialized directly into the
18 // channel we avoid one copy.
19 void* SharedMemIPCClient::GetBuffer() {
20 bool failure = false;
21 size_t ix = LockFreeChannel(&failure);
22 if (failure) {
23 return NULL;
24 }
25 return reinterpret_cast<char*>(control_) +
26 control_->channels[ix].channel_base;
27 }
28
29 // If we need to cancel an IPC before issuing DoCall
30 // our client should call FreeBuffer with the same pointer
31 // returned by GetBuffer.
32 void SharedMemIPCClient::FreeBuffer(void* buffer) {
33 size_t num = ChannelIndexFromBuffer(buffer);
34 ChannelControl* channel = control_->channels;
35 LONG result = ::InterlockedExchange(&channel[num].state, kFreeChannel);
36 DCHECK_NE(kFreeChannel, static_cast<ChannelState>(result));
37 }
38
39 // The constructor simply casts the shared memory to the internal
40 // structures. This is a cheap step that is why this IPC object can
41 // and should be constructed per call.
42 SharedMemIPCClient::SharedMemIPCClient(void* shared_mem)
43 : control_(reinterpret_cast<IPCControl*>(shared_mem)) {
44 first_base_ = reinterpret_cast<char*>(shared_mem) +
45 control_->channels[0].channel_base;
46 // There must be at least one channel.
47 DCHECK(0 != control_->channels_count);
48 }
49
50 // Do the IPC. At this point the channel should have already been
51 // filled with the serialized input parameters.
52 // We follow the pattern explained in the header file.
53 ResultCode SharedMemIPCClient::DoCall(CrossCallParams* params,
54 CrossCallReturn* answer) {
55 if (!control_->server_alive)
56 return SBOX_ERROR_CHANNEL_ERROR;
57
58 size_t num = ChannelIndexFromBuffer(params->GetBuffer());
59 ChannelControl* channel = control_->channels;
60 // Note that the IPC tag goes outside the buffer as well inside
61 // the buffer. This should enable the server to prioritize based on
62 // IPC tags without having to de-serialize the entire message.
63 channel[num].ipc_tag = params->GetTag();
64
65 // Wait for the server to service this IPC call. After kIPCWaitTimeOut1
66 // we check if the server_alive mutex was abandoned which will indicate
67 // that the server has died.
68
69 // While the atomic signaling and waiting is not a requirement, it
70 // is nice because we save a trip to kernel.
71 DWORD wait = ::SignalObjectAndWait(channel[num].ping_event,
72 channel[num].pong_event,
73 kIPCWaitTimeOut1, FALSE);
74 if (WAIT_TIMEOUT == wait) {
75 // The server is taking too long. Enter a loop were we check if the
76 // server_alive mutex has been abandoned which would signal a server crash
77 // or else we keep waiting for a response.
78 while (true) {
79 wait = ::WaitForSingleObject(control_->server_alive, 0);
80 if (WAIT_TIMEOUT == wait) {
81 // Server seems still alive. We already signaled so here we just wait.
82 wait = ::WaitForSingleObject(channel[num].pong_event, kIPCWaitTimeOut1);
83 if (WAIT_OBJECT_0 == wait) {
84 // The server took a long time but responded.
85 break;
86 } else if (WAIT_TIMEOUT == wait) {
87 continue;
88 } else {
89 return SBOX_ERROR_CHANNEL_ERROR;
90 }
91 } else {
92 // The server has crashed and windows has signaled the mutex as
93 // abandoned.
94 ::InterlockedExchange(&channel[num].state, kAbandonedChannel);
95 control_->server_alive = 0;
96 return SBOX_ERROR_CHANNEL_ERROR;
97 }
98 }
99 } else if (WAIT_OBJECT_0 != wait) {
100 // Probably the server crashed before the kIPCWaitTimeOut1 occurred.
101 return SBOX_ERROR_CHANNEL_ERROR;
102 }
103
104 // The server has returned an answer, copy it and free the channel.
105 memcpy(answer, params->GetCallReturn(), sizeof(CrossCallReturn));
106
107 // Return the IPC state It can indicate that while the IPC has
108 // completed some error in the Broker has caused to not return valid
109 // results.
110 return answer->call_outcome;
111 }
112
113 // Locking a channel is a simple as looping over all the channels
114 // looking for one that is has state = kFreeChannel and atomically
115 // swapping it to kBusyChannel.
116 // If there is no free channel, then we must back off so some other
117 // thread makes progress and frees a channel. To back off we sleep.
118 size_t SharedMemIPCClient::LockFreeChannel(bool* severe_failure) {
119 if (0 == control_->channels_count) {
120 *severe_failure = true;
121 return 0;
122 }
123 ChannelControl* channel = control_->channels;
124 do {
125 for (size_t ix = 0; ix != control_->channels_count; ++ix) {
126 if (kFreeChannel == ::InterlockedCompareExchange(&channel[ix].state,
127 kBusyChannel,
128 kFreeChannel)) {
129 *severe_failure = false;
130 return ix;
131 }
132 }
133 // We did not find any available channel, maybe the server is dead.
134 DWORD wait = ::WaitForSingleObject(control_->server_alive,
135 kIPCWaitTimeOut2);
136 if (WAIT_TIMEOUT != wait) {
137 // The server is dead and we outlive it enough to get in trouble.
138 *severe_failure = true;
139 return 0;
140 }
141 }
142 while (true);
143 }
144
145 // Find out which channel we are from the pointer returned by GetBuffer.
146 size_t SharedMemIPCClient::ChannelIndexFromBuffer(const void* buffer) {
147 ptrdiff_t d = reinterpret_cast<const char*>(buffer) - first_base_;
148 size_t num = d/kIPCChannelSize;
149 DCHECK_LT(num, control_->channels_count);
150 return (num);
151 }
152
153 } // namespace sandbox
OLDNEW
« no previous file with comments | « sandbox/win/src/sharedmem_ipc_client.h ('k') | sandbox/win/src/sharedmem_ipc_server.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698