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 |