| 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 |