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 |