OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/common/service_process_util_posix.h" | 5 #include "chrome/common/service_process_util_posix.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <memory> | 9 #include <utility> |
10 | 10 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/location.h" | 12 #include "base/location.h" |
13 #include "base/posix/eintr_wrapper.h" | 13 #include "base/posix/eintr_wrapper.h" |
14 #include "base/single_thread_task_runner.h" | |
15 #include "base/synchronization/waitable_event.h" | 14 #include "base/synchronization/waitable_event.h" |
16 #include "build/build_config.h" | |
17 #include "chrome/common/multi_process_lock.h" | 15 #include "chrome/common/multi_process_lock.h" |
18 | 16 |
19 namespace { | 17 namespace { |
20 int g_signal_socket = -1; | 18 int g_signal_socket = -1; |
21 } | 19 } |
22 | 20 |
23 // Attempts to take a lock named |name|. If |waiting| is true then this will | 21 // Attempts to take a lock named |name|. If |waiting| is true then this will |
24 // make multiple attempts to acquire the lock. | 22 // make multiple attempts to acquire the lock. |
25 // Caller is responsible for ownership of the MultiProcessLock. | 23 // Caller is responsible for ownership of the MultiProcessLock. |
26 MultiProcessLock* TakeNamedLock(const std::string& name, bool waiting) { | 24 MultiProcessLock* TakeNamedLock(const std::string& name, bool waiting) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 } | 80 } |
83 } | 81 } |
84 | 82 |
85 ServiceProcessState::StateData::StateData() : set_action(false) { | 83 ServiceProcessState::StateData::StateData() : set_action(false) { |
86 memset(sockets, -1, sizeof(sockets)); | 84 memset(sockets, -1, sizeof(sockets)); |
87 memset(&old_action, 0, sizeof(old_action)); | 85 memset(&old_action, 0, sizeof(old_action)); |
88 } | 86 } |
89 | 87 |
90 void ServiceProcessState::StateData::SignalReady(base::WaitableEvent* signal, | 88 void ServiceProcessState::StateData::SignalReady(base::WaitableEvent* signal, |
91 bool* success) { | 89 bool* success) { |
| 90 DCHECK(task_runner->BelongsToCurrentThread()); |
92 DCHECK_EQ(g_signal_socket, -1); | 91 DCHECK_EQ(g_signal_socket, -1); |
93 DCHECK(!signal->IsSignaled()); | 92 DCHECK(!signal->IsSignaled()); |
94 *success = base::MessageLoopForIO::current()->WatchFileDescriptor( | 93 *success = base::MessageLoopForIO::current()->WatchFileDescriptor( |
95 sockets[0], | 94 sockets[0], |
96 true, | 95 true, |
97 base::MessageLoopForIO::WATCH_READ, | 96 base::MessageLoopForIO::WATCH_READ, |
98 &watcher, | 97 &watcher, |
99 terminate_monitor.get()); | 98 terminate_monitor.get()); |
100 if (!*success) { | 99 if (!*success) { |
101 DLOG(ERROR) << "WatchFileDescriptor"; | 100 DLOG(ERROR) << "WatchFileDescriptor"; |
(...skipping 28 matching lines...) Expand all Loading... |
130 signal->Signal(); | 129 signal->Signal(); |
131 return; | 130 return; |
132 } | 131 } |
133 #elif defined(OS_POSIX) | 132 #elif defined(OS_POSIX) |
134 initializing_lock.reset(); | 133 initializing_lock.reset(); |
135 #endif // OS_POSIX | 134 #endif // OS_POSIX |
136 signal->Signal(); | 135 signal->Signal(); |
137 } | 136 } |
138 | 137 |
139 ServiceProcessState::StateData::~StateData() { | 138 ServiceProcessState::StateData::~StateData() { |
| 139 // StateData is destroyed on the thread that called SignalReady() (if any) to |
| 140 // satisfy the requirement that base::FilePathWatcher is destroyed in sequence |
| 141 // with base::FilePathWatcher::Watch(). |
| 142 DCHECK(!task_runner || task_runner->BelongsToCurrentThread()); |
| 143 |
140 if (sockets[0] != -1) { | 144 if (sockets[0] != -1) { |
141 if (IGNORE_EINTR(close(sockets[0]))) { | 145 if (IGNORE_EINTR(close(sockets[0]))) { |
142 DPLOG(ERROR) << "close"; | 146 DPLOG(ERROR) << "close"; |
143 } | 147 } |
144 } | 148 } |
145 if (sockets[1] != -1) { | 149 if (sockets[1] != -1) { |
146 if (IGNORE_EINTR(close(sockets[1]))) { | 150 if (IGNORE_EINTR(close(sockets[1]))) { |
147 DPLOG(ERROR) << "close"; | 151 DPLOG(ERROR) << "close"; |
148 } | 152 } |
149 } | 153 } |
150 if (set_action) { | 154 if (set_action) { |
151 if (sigaction(SIGTERM, &old_action, NULL) < 0) { | 155 if (sigaction(SIGTERM, &old_action, NULL) < 0) { |
152 DPLOG(ERROR) << "sigaction"; | 156 DPLOG(ERROR) << "sigaction"; |
153 } | 157 } |
154 } | 158 } |
155 g_signal_socket = -1; | 159 g_signal_socket = -1; |
156 } | 160 } |
157 | 161 |
158 void ServiceProcessState::CreateState() { | 162 void ServiceProcessState::CreateState() { |
159 DCHECK(!state_); | 163 DCHECK(!state_); |
160 state_ = new StateData; | 164 state_ = new StateData(); |
161 | |
162 // Explicitly adding a reference here (and removing it in TearDownState) | |
163 // because StateData is refcounted on Mac and Linux so that methods can | |
164 // be called on other threads. | |
165 // It is not refcounted on Windows at this time. | |
166 state_->AddRef(); | |
167 } | 165 } |
168 | 166 |
169 bool ServiceProcessState::SignalReady(base::SingleThreadTaskRunner* task_runner, | 167 bool ServiceProcessState::SignalReady( |
170 const base::Closure& terminate_task) { | 168 scoped_refptr<base::SingleThreadTaskRunner> task_runner, |
| 169 const base::Closure& terminate_task) { |
| 170 DCHECK(task_runner); |
171 DCHECK(state_); | 171 DCHECK(state_); |
172 | 172 |
173 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 173 #if !defined(OS_MACOSX) |
174 state_->running_lock.reset(TakeServiceRunningLock(true)); | 174 state_->running_lock.reset(TakeServiceRunningLock(true)); |
175 if (state_->running_lock.get() == NULL) { | 175 if (state_->running_lock.get() == NULL) { |
176 return false; | 176 return false; |
177 } | 177 } |
178 #endif | 178 #endif |
179 state_->terminate_monitor.reset( | 179 state_->terminate_monitor.reset( |
180 new ServiceProcessTerminateMonitor(terminate_task)); | 180 new ServiceProcessTerminateMonitor(terminate_task)); |
181 if (pipe(state_->sockets) < 0) { | 181 if (pipe(state_->sockets) < 0) { |
182 DPLOG(ERROR) << "pipe"; | 182 DPLOG(ERROR) << "pipe"; |
183 return false; | 183 return false; |
184 } | 184 } |
185 base::WaitableEvent signal_ready( | 185 base::WaitableEvent signal_ready( |
186 base::WaitableEvent::ResetPolicy::MANUAL, | 186 base::WaitableEvent::ResetPolicy::MANUAL, |
187 base::WaitableEvent::InitialState::NOT_SIGNALED); | 187 base::WaitableEvent::InitialState::NOT_SIGNALED); |
188 bool success = false; | 188 bool success = false; |
189 | 189 |
190 task_runner->PostTask(FROM_HERE, | 190 state_->task_runner = std::move(task_runner); |
191 base::Bind(&ServiceProcessState::StateData::SignalReady, | 191 state_->task_runner->PostTask( |
192 state_, &signal_ready, &success)); | 192 FROM_HERE, base::Bind(&ServiceProcessState::StateData::SignalReady, |
| 193 base::Unretained(state_), &signal_ready, &success)); |
193 signal_ready.Wait(); | 194 signal_ready.Wait(); |
194 return success; | 195 return success; |
195 } | 196 } |
196 | 197 |
197 void ServiceProcessState::TearDownState() { | 198 void ServiceProcessState::TearDownState() { |
198 if (state_) { | 199 if (state_ && state_->task_runner) |
199 state_->Release(); | 200 state_->task_runner->DeleteSoon(FROM_HERE, state_); |
200 state_ = NULL; | 201 else |
201 } | 202 delete state_; |
| 203 state_ = nullptr; |
202 } | 204 } |
OLD | NEW |