| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/eintr_wrapper.h" | 8 #include "base/eintr_wrapper.h" |
| 9 #include "base/message_loop_proxy.h" | 9 #include "base/message_loop_proxy.h" |
| 10 #include "base/synchronization/waitable_event.h" | 10 #include "base/synchronization/waitable_event.h" |
| 11 | 11 |
| 12 namespace { | 12 namespace { |
| 13 int g_signal_socket = -1; | 13 int g_signal_socket = -1; |
| 14 } | 14 } |
| 15 | 15 |
| 16 ServiceProcessShutdownMonitor::ServiceProcessShutdownMonitor( | 16 ServiceProcessTerminateMonitor::ServiceProcessTerminateMonitor( |
| 17 Task* shutdown_task) | 17 Task* terminate_task) |
| 18 : shutdown_task_(shutdown_task) { | 18 : terminate_task_(terminate_task) { |
| 19 } | 19 } |
| 20 | 20 |
| 21 ServiceProcessShutdownMonitor::~ServiceProcessShutdownMonitor() { | 21 ServiceProcessTerminateMonitor::~ServiceProcessTerminateMonitor() { |
| 22 } | 22 } |
| 23 | 23 |
| 24 void ServiceProcessShutdownMonitor::OnFileCanReadWithoutBlocking(int fd) { | 24 void ServiceProcessTerminateMonitor::OnFileCanReadWithoutBlocking(int fd) { |
| 25 if (shutdown_task_.get()) { | 25 if (terminate_task_.get()) { |
| 26 int buffer; | 26 int buffer; |
| 27 int length = read(fd, &buffer, sizeof(buffer)); | 27 int length = read(fd, &buffer, sizeof(buffer)); |
| 28 if ((length == sizeof(buffer)) && (buffer == kShutDownMessage)) { | 28 if ((length == sizeof(buffer)) && (buffer == kTerminateMessage)) { |
| 29 shutdown_task_->Run(); | 29 terminate_task_->Run(); |
| 30 shutdown_task_.reset(); | 30 terminate_task_.reset(); |
| 31 } else if (length > 0) { | 31 } else if (length > 0) { |
| 32 LOG(ERROR) << "Unexpected read: " << buffer; | 32 LOG(ERROR) << "Unexpected read: " << buffer; |
| 33 } else if (length == 0) { | 33 } else if (length == 0) { |
| 34 LOG(ERROR) << "Unexpected fd close"; | 34 LOG(ERROR) << "Unexpected fd close"; |
| 35 } else if (length < 0) { | 35 } else if (length < 0) { |
| 36 PLOG(ERROR) << "read"; | 36 PLOG(ERROR) << "read"; |
| 37 } | 37 } |
| 38 } | 38 } |
| 39 } | 39 } |
| 40 | 40 |
| 41 void ServiceProcessShutdownMonitor::OnFileCanWriteWithoutBlocking(int fd) { | 41 void ServiceProcessTerminateMonitor::OnFileCanWriteWithoutBlocking(int fd) { |
| 42 NOTIMPLEMENTED(); | 42 NOTIMPLEMENTED(); |
| 43 } | 43 } |
| 44 | 44 |
| 45 // "Forced" Shutdowns on POSIX are done via signals. The magic signal for | 45 // "Forced" Shutdowns on POSIX are done via signals. The magic signal for |
| 46 // a shutdown is SIGTERM. "write" is a signal safe function. PLOG(ERROR) is | 46 // a shutdown is SIGTERM. "write" is a signal safe function. PLOG(ERROR) is |
| 47 // not, but we don't ever expect it to be called. | 47 // not, but we don't ever expect it to be called. |
| 48 static void SigTermHandler(int sig, siginfo_t* info, void* uap) { | 48 static void SigTermHandler(int sig, siginfo_t* info, void* uap) { |
| 49 // TODO(dmaclach): add security here to make sure that we are being shut | 49 // TODO(dmaclach): add security here to make sure that we are being shut |
| 50 // down by an appropriate process. | 50 // down by an appropriate process. |
| 51 int message = ServiceProcessShutdownMonitor::kShutDownMessage; | 51 int message = ServiceProcessTerminateMonitor::kTerminateMessage; |
| 52 if (write(g_signal_socket, &message, sizeof(message)) < 0) { | 52 if (write(g_signal_socket, &message, sizeof(message)) < 0) { |
| 53 PLOG(ERROR) << "write"; | 53 PLOG(ERROR) << "write"; |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 | 56 |
| 57 ServiceProcessState::StateData::StateData() : set_action_(false) { | 57 ServiceProcessState::StateData::StateData() : set_action_(false) { |
| 58 memset(sockets_, -1, sizeof(sockets_)); | 58 memset(sockets_, -1, sizeof(sockets_)); |
| 59 memset(&old_action_, 0, sizeof(old_action_)); | 59 memset(&old_action_, 0, sizeof(old_action_)); |
| 60 } | 60 } |
| 61 | 61 |
| 62 void ServiceProcessState::StateData::SignalReady(base::WaitableEvent* signal, | 62 void ServiceProcessState::StateData::SignalReady(base::WaitableEvent* signal, |
| 63 bool* success) { | 63 bool* success) { |
| 64 CHECK_EQ(g_signal_socket, -1); | 64 CHECK_EQ(g_signal_socket, -1); |
| 65 CHECK(!signal->IsSignaled()); | 65 CHECK(!signal->IsSignaled()); |
| 66 *success = MessageLoopForIO::current()->WatchFileDescriptor( | 66 *success = MessageLoopForIO::current()->WatchFileDescriptor( |
| 67 sockets_[0], true, MessageLoopForIO::WATCH_READ, | 67 sockets_[0], true, MessageLoopForIO::WATCH_READ, |
| 68 &watcher_, shut_down_monitor_.get()); | 68 &watcher_, terminate_monitor_.get()); |
| 69 if (!*success) { | 69 if (!*success) { |
| 70 LOG(ERROR) << "WatchFileDescriptor"; | 70 LOG(ERROR) << "WatchFileDescriptor"; |
| 71 signal->Signal(); | 71 signal->Signal(); |
| 72 return; | 72 return; |
| 73 } | 73 } |
| 74 g_signal_socket = sockets_[1]; | 74 g_signal_socket = sockets_[1]; |
| 75 | 75 |
| 76 // Set up signal handler for SIGTERM. | 76 // Set up signal handler for SIGTERM. |
| 77 struct sigaction action; | 77 struct sigaction action; |
| 78 action.sa_sigaction = SigTermHandler; | 78 action.sa_sigaction = SigTermHandler; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 state_ = new StateData; | 128 state_ = new StateData; |
| 129 | 129 |
| 130 // Explicitly adding a reference here (and removing it in TearDownState) | 130 // Explicitly adding a reference here (and removing it in TearDownState) |
| 131 // because StateData is refcounted on Mac and Linux so that methods can | 131 // because StateData is refcounted on Mac and Linux so that methods can |
| 132 // be called on other threads. | 132 // be called on other threads. |
| 133 // It is not refcounted on Windows at this time. | 133 // It is not refcounted on Windows at this time. |
| 134 state_->AddRef(); | 134 state_->AddRef(); |
| 135 } | 135 } |
| 136 | 136 |
| 137 bool ServiceProcessState::SignalReady( | 137 bool ServiceProcessState::SignalReady( |
| 138 base::MessageLoopProxy* message_loop_proxy, Task* shutdown_task) { | 138 base::MessageLoopProxy* message_loop_proxy, Task* terminate_task) { |
| 139 CHECK(state_); | 139 CHECK(state_); |
| 140 | 140 |
| 141 scoped_ptr<Task> scoped_shutdown_task(shutdown_task); | 141 scoped_ptr<Task> scoped_terminate_task(terminate_task); |
| 142 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 142 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 143 state_->running_lock_.reset(TakeServiceRunningLock(true)); | 143 state_->running_lock_.reset(TakeServiceRunningLock(true)); |
| 144 if (state_->running_lock_.get() == NULL) { | 144 if (state_->running_lock_.get() == NULL) { |
| 145 return false; | 145 return false; |
| 146 } | 146 } |
| 147 #endif | 147 #endif |
| 148 state_->shut_down_monitor_.reset( | 148 state_->terminate_monitor_.reset( |
| 149 new ServiceProcessShutdownMonitor(scoped_shutdown_task.release())); | 149 new ServiceProcessTerminateMonitor(scoped_terminate_task.release())); |
| 150 if (pipe(state_->sockets_) < 0) { | 150 if (pipe(state_->sockets_) < 0) { |
| 151 PLOG(ERROR) << "pipe"; | 151 PLOG(ERROR) << "pipe"; |
| 152 return false; | 152 return false; |
| 153 } | 153 } |
| 154 base::WaitableEvent signal_ready(true, false); | 154 base::WaitableEvent signal_ready(true, false); |
| 155 bool success = false; | 155 bool success = false; |
| 156 | 156 |
| 157 message_loop_proxy->PostTask(FROM_HERE, | 157 message_loop_proxy->PostTask(FROM_HERE, |
| 158 NewRunnableMethod(state_, &ServiceProcessState::StateData::SignalReady, | 158 NewRunnableMethod(state_, &ServiceProcessState::StateData::SignalReady, |
| 159 &signal_ready, | 159 &signal_ready, |
| 160 &success)); | 160 &success)); |
| 161 signal_ready.Wait(); | 161 signal_ready.Wait(); |
| 162 return success; | 162 return success; |
| 163 } | 163 } |
| 164 | 164 |
| 165 void ServiceProcessState::TearDownState() { | 165 void ServiceProcessState::TearDownState() { |
| 166 if (state_) { | 166 if (state_) { |
| 167 state_->Release(); | 167 state_->Release(); |
| 168 state_ = NULL; | 168 state_ = NULL; |
| 169 } | 169 } |
| 170 } | 170 } |
| OLD | NEW |