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 <utility> | 9 #include <memory> |
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" |
14 #include "base/synchronization/waitable_event.h" | 15 #include "base/synchronization/waitable_event.h" |
| 16 #include "build/build_config.h" |
15 #include "chrome/common/multi_process_lock.h" | 17 #include "chrome/common/multi_process_lock.h" |
16 | 18 |
17 namespace { | 19 namespace { |
18 int g_signal_socket = -1; | 20 int g_signal_socket = -1; |
19 } | 21 } |
20 | 22 |
21 // Attempts to take a lock named |name|. If |waiting| is true then this will | 23 // Attempts to take a lock named |name|. If |waiting| is true then this will |
22 // make multiple attempts to acquire the lock. | 24 // make multiple attempts to acquire the lock. |
23 // Caller is responsible for ownership of the MultiProcessLock. | 25 // Caller is responsible for ownership of the MultiProcessLock. |
24 MultiProcessLock* TakeNamedLock(const std::string& name, bool waiting) { | 26 MultiProcessLock* TakeNamedLock(const std::string& name, bool waiting) { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 } | 82 } |
81 } | 83 } |
82 | 84 |
83 ServiceProcessState::StateData::StateData() : set_action(false) { | 85 ServiceProcessState::StateData::StateData() : set_action(false) { |
84 memset(sockets, -1, sizeof(sockets)); | 86 memset(sockets, -1, sizeof(sockets)); |
85 memset(&old_action, 0, sizeof(old_action)); | 87 memset(&old_action, 0, sizeof(old_action)); |
86 } | 88 } |
87 | 89 |
88 void ServiceProcessState::StateData::SignalReady(base::WaitableEvent* signal, | 90 void ServiceProcessState::StateData::SignalReady(base::WaitableEvent* signal, |
89 bool* success) { | 91 bool* success) { |
90 DCHECK(task_runner->BelongsToCurrentThread()); | |
91 DCHECK_EQ(g_signal_socket, -1); | 92 DCHECK_EQ(g_signal_socket, -1); |
92 DCHECK(!signal->IsSignaled()); | 93 DCHECK(!signal->IsSignaled()); |
93 *success = base::MessageLoopForIO::current()->WatchFileDescriptor( | 94 *success = base::MessageLoopForIO::current()->WatchFileDescriptor( |
94 sockets[0], | 95 sockets[0], |
95 true, | 96 true, |
96 base::MessageLoopForIO::WATCH_READ, | 97 base::MessageLoopForIO::WATCH_READ, |
97 &watcher, | 98 &watcher, |
98 terminate_monitor.get()); | 99 terminate_monitor.get()); |
99 if (!*success) { | 100 if (!*success) { |
100 DLOG(ERROR) << "WatchFileDescriptor"; | 101 DLOG(ERROR) << "WatchFileDescriptor"; |
(...skipping 28 matching lines...) Expand all Loading... |
129 signal->Signal(); | 130 signal->Signal(); |
130 return; | 131 return; |
131 } | 132 } |
132 #elif defined(OS_POSIX) | 133 #elif defined(OS_POSIX) |
133 initializing_lock.reset(); | 134 initializing_lock.reset(); |
134 #endif // OS_POSIX | 135 #endif // OS_POSIX |
135 signal->Signal(); | 136 signal->Signal(); |
136 } | 137 } |
137 | 138 |
138 ServiceProcessState::StateData::~StateData() { | 139 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 | |
144 if (sockets[0] != -1) { | 140 if (sockets[0] != -1) { |
145 if (IGNORE_EINTR(close(sockets[0]))) { | 141 if (IGNORE_EINTR(close(sockets[0]))) { |
146 DPLOG(ERROR) << "close"; | 142 DPLOG(ERROR) << "close"; |
147 } | 143 } |
148 } | 144 } |
149 if (sockets[1] != -1) { | 145 if (sockets[1] != -1) { |
150 if (IGNORE_EINTR(close(sockets[1]))) { | 146 if (IGNORE_EINTR(close(sockets[1]))) { |
151 DPLOG(ERROR) << "close"; | 147 DPLOG(ERROR) << "close"; |
152 } | 148 } |
153 } | 149 } |
154 if (set_action) { | 150 if (set_action) { |
155 if (sigaction(SIGTERM, &old_action, NULL) < 0) { | 151 if (sigaction(SIGTERM, &old_action, NULL) < 0) { |
156 DPLOG(ERROR) << "sigaction"; | 152 DPLOG(ERROR) << "sigaction"; |
157 } | 153 } |
158 } | 154 } |
159 g_signal_socket = -1; | 155 g_signal_socket = -1; |
160 } | 156 } |
161 | 157 |
162 void ServiceProcessState::CreateState() { | 158 void ServiceProcessState::CreateState() { |
163 DCHECK(!state_); | 159 DCHECK(!state_); |
164 state_ = new StateData(); | 160 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(); |
165 } | 167 } |
166 | 168 |
167 bool ServiceProcessState::SignalReady( | 169 bool ServiceProcessState::SignalReady(base::SingleThreadTaskRunner* task_runner, |
168 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | 170 const base::Closure& terminate_task) { |
169 const base::Closure& terminate_task) { | |
170 DCHECK(task_runner); | |
171 DCHECK(state_); | 171 DCHECK(state_); |
172 | 172 |
173 #if !defined(OS_MACOSX) | 173 #if defined(OS_POSIX) && !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 state_->task_runner = std::move(task_runner); | 190 task_runner->PostTask(FROM_HERE, |
191 state_->task_runner->PostTask( | 191 base::Bind(&ServiceProcessState::StateData::SignalReady, |
192 FROM_HERE, base::Bind(&ServiceProcessState::StateData::SignalReady, | 192 state_, &signal_ready, &success)); |
193 base::Unretained(state_), &signal_ready, &success)); | |
194 signal_ready.Wait(); | 193 signal_ready.Wait(); |
195 return success; | 194 return success; |
196 } | 195 } |
197 | 196 |
198 void ServiceProcessState::TearDownState() { | 197 void ServiceProcessState::TearDownState() { |
199 if (state_ && state_->task_runner) | 198 if (state_) { |
200 state_->task_runner->DeleteSoon(FROM_HERE, state_); | 199 state_->Release(); |
201 else | 200 state_ = NULL; |
202 delete state_; | 201 } |
203 state_ = nullptr; | |
204 } | 202 } |
OLD | NEW |