OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 25 matching lines...) Expand all Loading... |
36 mach_msg_header_t* Header() const { | 36 mach_msg_header_t* Header() const { |
37 return reinterpret_cast<mach_msg_header_t*>(vm_.address()); | 37 return reinterpret_cast<mach_msg_header_t*>(vm_.address()); |
38 } | 38 } |
39 | 39 |
40 //! \brief Ensures that this object has a buffer of exactly \a size bytes | 40 //! \brief Ensures that this object has a buffer of exactly \a size bytes |
41 //! available. | 41 //! available. |
42 //! | 42 //! |
43 //! If the existing buffer is a different size, it will be reallocated without | 43 //! If the existing buffer is a different size, it will be reallocated without |
44 //! copying any of the old buffer’s contents to the new buffer. The contents | 44 //! copying any of the old buffer’s contents to the new buffer. The contents |
45 //! of the buffer are unspecified after this call, even if no reallocation is | 45 //! of the buffer are unspecified after this call, even if no reallocation is |
46 //! made. | 46 //! performed. |
47 kern_return_t Reallocate(vm_size_t size) { | 47 kern_return_t Reallocate(vm_size_t size) { |
48 // This test uses == instead of > so that a large reallocation to receive a | 48 // This test uses == instead of > so that a large reallocation to receive a |
49 // large message doesn’t cause permanent memory bloat for the duration of | 49 // large message doesn’t cause permanent memory bloat for the duration of |
50 // a MachMessageServer::Run() loop. | 50 // a MachMessageServer::Run() loop. |
51 if (size == vm_.size()) { | 51 if (size == vm_.size()) { |
52 return KERN_SUCCESS; | 52 return KERN_SUCCESS; |
53 } | 53 } |
54 | 54 |
55 // reset() first, so that two allocations don’t exist simultaneously. | 55 // reset() first, so that two allocations don’t exist simultaneously. |
56 vm_.reset(); | 56 vm_.reset(); |
57 | 57 |
58 vm_address_t address; | 58 if (size) { |
59 kern_return_t kr = | 59 vm_address_t address; |
60 vm_allocate(mach_task_self(), | 60 kern_return_t kr = |
61 &address, | 61 vm_allocate(mach_task_self(), |
62 size, | 62 &address, |
63 VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_MEMORY_MACH_MSG)); | 63 size, |
64 if (kr != KERN_SUCCESS) { | 64 VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_MEMORY_MACH_MSG)); |
65 return kr; | 65 if (kr != KERN_SUCCESS) { |
| 66 return kr; |
| 67 } |
| 68 |
| 69 vm_.reset(address, size); |
66 } | 70 } |
67 | 71 |
68 vm_.reset(address, size); | |
69 return KERN_SUCCESS; | 72 return KERN_SUCCESS; |
70 } | 73 } |
71 | 74 |
72 private: | 75 private: |
73 base::mac::ScopedMachVM vm_; | 76 base::mac::ScopedMachVM vm_; |
74 | 77 |
75 DISALLOW_COPY_AND_ASSIGN(MachMessageBuffer); | 78 DISALLOW_COPY_AND_ASSIGN(MachMessageBuffer); |
76 }; | 79 }; |
77 | 80 |
78 // Wraps MachMessageWithDeadline(), using a MachMessageBuffer argument which | 81 // Wraps MachMessageWithDeadline(), using a MachMessageBuffer argument which |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 } else { | 137 } else { |
135 options &= ~MACH_RCV_LARGE; | 138 options &= ~MACH_RCV_LARGE; |
136 } | 139 } |
137 | 140 |
138 const mach_msg_size_t trailer_alloc = REQUESTED_TRAILER_SIZE(options); | 141 const mach_msg_size_t trailer_alloc = REQUESTED_TRAILER_SIZE(options); |
139 const mach_msg_size_t expected_receive_size = | 142 const mach_msg_size_t expected_receive_size = |
140 round_msg(interface->MachMessageServerRequestSize()) + trailer_alloc; | 143 round_msg(interface->MachMessageServerRequestSize()) + trailer_alloc; |
141 const mach_msg_size_t request_size = (receive_large == kReceiveLargeResize) | 144 const mach_msg_size_t request_size = (receive_large == kReceiveLargeResize) |
142 ? round_page(expected_receive_size) | 145 ? round_page(expected_receive_size) |
143 : expected_receive_size; | 146 : expected_receive_size; |
| 147 DCHECK_GE(request_size, sizeof(mach_msg_empty_rcv_t)); |
144 | 148 |
145 // mach_msg_server() and mach_msg_server_once() would consider whether | 149 // mach_msg_server() and mach_msg_server_once() would consider whether |
146 // |options| contains MACH_SEND_TRAILER and include MAX_TRAILER_SIZE in this | 150 // |options| contains MACH_SEND_TRAILER and include MAX_TRAILER_SIZE in this |
147 // computation if it does, but that option is ineffective on OS X. | 151 // computation if it does, but that option is ineffective on OS X. |
148 const mach_msg_size_t reply_alloc = | 152 const mach_msg_size_t reply_size = interface->MachMessageServerReplySize(); |
149 round_page(interface->MachMessageServerReplySize()); | 153 DCHECK_GE(reply_size, sizeof(mach_msg_empty_send_t)); |
| 154 const mach_msg_size_t reply_alloc = round_page(reply_size); |
150 | 155 |
151 MachMessageBuffer request; | 156 MachMessageBuffer request; |
152 MachMessageBuffer reply; | 157 MachMessageBuffer reply; |
153 bool received_any_request = false; | 158 bool received_any_request = false; |
154 bool retry; | 159 bool retry; |
155 | 160 |
156 kern_return_t kr; | 161 kern_return_t kr; |
157 | 162 |
158 do { | 163 do { |
159 retry = false; | 164 retry = false; |
(...skipping 17 matching lines...) Expand all Loading... |
177 // alternatives, which might involve returning MACH_MSG_SUCCESS, | 182 // alternatives, which might involve returning MACH_MSG_SUCCESS, |
178 // MACH_RCV_TIMED_OUT, or MACH_RCV_TOO_LARGE to a caller that | 183 // MACH_RCV_TIMED_OUT, or MACH_RCV_TOO_LARGE to a caller that |
179 // specified one-shot behavior, all seem less correct than retrying. | 184 // specified one-shot behavior, all seem less correct than retrying. |
180 MACH_LOG(WARNING, kr) << "mach_msg: ignoring large message"; | 185 MACH_LOG(WARNING, kr) << "mach_msg: ignoring large message"; |
181 retry = true; | 186 retry = true; |
182 continue; | 187 continue; |
183 | 188 |
184 case kReceiveLargeResize: { | 189 case kReceiveLargeResize: { |
185 mach_msg_size_t this_request_size = round_page( | 190 mach_msg_size_t this_request_size = round_page( |
186 round_msg(request.Header()->msgh_size) + trailer_alloc); | 191 round_msg(request.Header()->msgh_size) + trailer_alloc); |
| 192 DCHECK_GT(this_request_size, request_size); |
187 | 193 |
188 kr = MachMessageAllocateReceive(&request, | 194 kr = MachMessageAllocateReceive(&request, |
189 options & ~MACH_RCV_LARGE, | 195 options & ~MACH_RCV_LARGE, |
190 this_request_size, | 196 this_request_size, |
191 receive_port, | 197 receive_port, |
192 deadline, | 198 deadline, |
193 MACH_PORT_NULL, | 199 MACH_PORT_NULL, |
194 !received_any_request); | 200 !received_any_request); |
195 | 201 |
196 break; | 202 break; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
265 } | 271 } |
266 return kr; | 272 return kr; |
267 } | 273 } |
268 } | 274 } |
269 } while (persistent == kPersistent || retry); | 275 } while (persistent == kPersistent || retry); |
270 | 276 |
271 return kr; | 277 return kr; |
272 } | 278 } |
273 | 279 |
274 } // namespace crashpad | 280 } // namespace crashpad |
OLD | NEW |