OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Crashpad Authors. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (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 |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 #include "handler/win/registration_server.h" |
| 16 |
| 17 #include <vector> |
| 18 |
| 19 #include "base/logging.h" |
| 20 #include "base/memory/scoped_ptr.h" |
| 21 #include "handler/win/registration_pipe_state.h" |
| 22 #include "util/stdlib/pointer_container.h" |
| 23 |
| 24 namespace crashpad { |
| 25 |
| 26 RegistrationServer::RegistrationServer() : stop_event_() { |
| 27 stop_event_.reset(CreateEvent(nullptr, false, false, nullptr)); |
| 28 DPCHECK(stop_event_.is_valid()); |
| 29 } |
| 30 |
| 31 RegistrationServer::~RegistrationServer() { |
| 32 } |
| 33 |
| 34 bool RegistrationServer::Run(const base::string16& pipe_name, |
| 35 Delegate* delegate) { |
| 36 if (!stop_event_.is_valid()) { |
| 37 LOG(ERROR) << "Failed to create stop_event_."; |
| 38 return false; |
| 39 } |
| 40 |
| 41 PointerVector<RegistrationPipeState> pipes; |
| 42 std::vector<HANDLE> handles; |
| 43 |
| 44 const int kNumPipes = 3; |
| 45 |
| 46 // Create the named pipes. |
| 47 for (int i = 0; i < kNumPipes; ++i) { |
| 48 DWORD open_mode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED; |
| 49 if (pipes.size() == 0) |
| 50 open_mode |= FILE_FLAG_FIRST_PIPE_INSTANCE; |
| 51 ScopedFileHANDLE pipe( |
| 52 CreateNamedPipe(pipe_name.c_str(), |
| 53 open_mode, |
| 54 PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, |
| 55 kNumPipes, |
| 56 512, // nOutBufferSize |
| 57 512, // nInBufferSize |
| 58 20, // nDefaultTimeOut |
| 59 nullptr)); // lpSecurityAttributes |
| 60 if (pipe.is_valid()) { |
| 61 scoped_ptr<RegistrationPipeState> pipe_state( |
| 62 new RegistrationPipeState(pipe.Pass(), delegate)); |
| 63 if (pipe_state->Initialize()) { |
| 64 pipes.push_back(pipe_state.release()); |
| 65 handles.push_back(pipes.back()->completion_event()); |
| 66 } |
| 67 } else { |
| 68 PLOG(ERROR) << "CreateNamedPipe"; |
| 69 } |
| 70 } |
| 71 |
| 72 if (pipes.size() == 0) { |
| 73 LOG(ERROR) << "Failed to initialize any pipes."; |
| 74 return false; |
| 75 } |
| 76 |
| 77 delegate->OnStarted(); |
| 78 |
| 79 // Add stop_event_ to the list of events we will observe. |
| 80 handles.push_back(stop_event_.get()); |
| 81 |
| 82 bool stopped = false; |
| 83 |
| 84 // Run the main loop, dispatching completion event signals to the pipe |
| 85 // instances. |
| 86 while (true) { |
| 87 DWORD wait_result = WaitForMultipleObjects( |
| 88 static_cast<DWORD>(handles.size()), handles.data(), false, INFINITE); |
| 89 if (wait_result >= WAIT_OBJECT_0 && |
| 90 wait_result < WAIT_OBJECT_0 + pipes.size()) { |
| 91 int index = wait_result - WAIT_OBJECT_0; |
| 92 // Handle a completion event. |
| 93 if (!pipes[index]->OnCompletion()) { |
| 94 pipes.erase(pipes.begin() + index); |
| 95 handles.erase(handles.begin() + index); |
| 96 } |
| 97 if (pipes.size()) |
| 98 continue; |
| 99 // Exit due to all pipes having failed. |
| 100 } else if (wait_result == WAIT_OBJECT_0 + pipes.size()) { |
| 101 // Exit due to stop_event_. |
| 102 stopped = true; |
| 103 } else if (wait_result == WAIT_FAILED) { |
| 104 // Exit due to error. |
| 105 PLOG(ERROR) << "WaitForMultipleObjects"; |
| 106 } else { |
| 107 // Exit due to unexpected return code. |
| 108 NOTREACHED(); |
| 109 } |
| 110 break; |
| 111 } |
| 112 |
| 113 // Remove |stop_event_| from the wait list. |
| 114 handles.pop_back(); |
| 115 |
| 116 // Cancel any ongoing asynchronous operations. |
| 117 for (auto& pipe : pipes) { |
| 118 pipe->Stop(); |
| 119 } |
| 120 |
| 121 // Wait until all of the pipe instances are ready to be destroyed. |
| 122 DWORD wait_result = WaitForMultipleObjects( |
| 123 static_cast<DWORD>(handles.size()), handles.data(), true, INFINITE); |
| 124 PCHECK(wait_result != WAIT_FAILED); |
| 125 DCHECK_GE(wait_result, WAIT_OBJECT_0); |
| 126 DCHECK_LT(wait_result, WAIT_OBJECT_0 + handles.size()); |
| 127 |
| 128 return stopped; |
| 129 } |
| 130 |
| 131 void RegistrationServer::Stop() { |
| 132 if (!SetEvent(stop_event_.get())) |
| 133 PLOG(FATAL) << "SetEvent"; |
| 134 } |
| 135 |
| 136 } // namespace crashpad |
OLD | NEW |