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" |
(...skipping 11 matching lines...) Expand all Loading... |
22 } | 22 } |
23 | 23 |
24 void ServiceProcessTerminateMonitor::OnFileCanReadWithoutBlocking(int fd) { | 24 void ServiceProcessTerminateMonitor::OnFileCanReadWithoutBlocking(int fd) { |
25 if (terminate_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 == kTerminateMessage)) { | 28 if ((length == sizeof(buffer)) && (buffer == kTerminateMessage)) { |
29 terminate_task_->Run(); | 29 terminate_task_->Run(); |
30 terminate_task_.reset(); | 30 terminate_task_.reset(); |
31 } else if (length > 0) { | 31 } else if (length > 0) { |
32 LOG(ERROR) << "Unexpected read: " << buffer; | 32 DLOG(ERROR) << "Unexpected read: " << buffer; |
33 } else if (length == 0) { | 33 } else if (length == 0) { |
34 LOG(ERROR) << "Unexpected fd close"; | 34 DLOG(ERROR) << "Unexpected fd close"; |
35 } else if (length < 0) { | 35 } else if (length < 0) { |
36 PLOG(ERROR) << "read"; | 36 DPLOG(ERROR) << "read"; |
37 } | 37 } |
38 } | 38 } |
39 } | 39 } |
40 | 40 |
41 void ServiceProcessTerminateMonitor::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 = ServiceProcessTerminateMonitor::kTerminateMessage; | 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 DPLOG(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 DCHECK_EQ(g_signal_socket, -1); |
65 CHECK(!signal->IsSignaled()); | 65 DCHECK(!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_, terminate_monitor_.get()); | 68 &watcher_, terminate_monitor_.get()); |
69 if (!*success) { | 69 if (!*success) { |
70 LOG(ERROR) << "WatchFileDescriptor"; | 70 DLOG(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 memset(&action, 0, sizeof(action)); | 78 memset(&action, 0, sizeof(action)); |
79 action.sa_sigaction = SigTermHandler; | 79 action.sa_sigaction = SigTermHandler; |
80 sigemptyset(&action.sa_mask); | 80 sigemptyset(&action.sa_mask); |
81 action.sa_flags = SA_SIGINFO; | 81 action.sa_flags = SA_SIGINFO; |
82 *success = sigaction(SIGTERM, &action, &old_action_) == 0; | 82 *success = sigaction(SIGTERM, &action, &old_action_) == 0; |
83 if (!*success) { | 83 if (!*success) { |
84 PLOG(ERROR) << "sigaction"; | 84 DPLOG(ERROR) << "sigaction"; |
85 signal->Signal(); | 85 signal->Signal(); |
86 return; | 86 return; |
87 } | 87 } |
88 | 88 |
89 // If the old_action is not default, somebody else has installed a | 89 // If the old_action is not default, somebody else has installed a |
90 // a competing handler. Our handler is going to override it so it | 90 // a competing handler. Our handler is going to override it so it |
91 // won't be called. If this occurs it needs to be fixed. | 91 // won't be called. If this occurs it needs to be fixed. |
92 DCHECK_EQ(old_action_.sa_handler, SIG_DFL); | 92 DCHECK_EQ(old_action_.sa_handler, SIG_DFL); |
93 set_action_ = true; | 93 set_action_ = true; |
94 | 94 |
95 #if defined(OS_MACOSX) | 95 #if defined(OS_MACOSX) |
96 *success = WatchExecutable(); | 96 *success = WatchExecutable(); |
97 if (!*success) { | 97 if (!*success) { |
98 LOG(ERROR) << "WatchExecutable"; | 98 DLOG(ERROR) << "WatchExecutable"; |
99 signal->Signal(); | 99 signal->Signal(); |
100 return; | 100 return; |
101 } | 101 } |
102 #elif defined(OS_POSIX) | 102 #elif defined(OS_POSIX) |
103 initializing_lock_.reset(); | 103 initializing_lock_.reset(); |
104 #endif // OS_POSIX | 104 #endif // OS_POSIX |
105 signal->Signal(); | 105 signal->Signal(); |
106 } | 106 } |
107 | 107 |
108 ServiceProcessState::StateData::~StateData() { | 108 ServiceProcessState::StateData::~StateData() { |
109 if (sockets_[0] != -1) { | 109 if (sockets_[0] != -1) { |
110 if (HANDLE_EINTR(close(sockets_[0]))) { | 110 if (HANDLE_EINTR(close(sockets_[0]))) { |
111 PLOG(ERROR) << "close"; | 111 DPLOG(ERROR) << "close"; |
112 } | 112 } |
113 } | 113 } |
114 if (sockets_[1] != -1) { | 114 if (sockets_[1] != -1) { |
115 if (HANDLE_EINTR(close(sockets_[1]))) { | 115 if (HANDLE_EINTR(close(sockets_[1]))) { |
116 PLOG(ERROR) << "close"; | 116 DPLOG(ERROR) << "close"; |
117 } | 117 } |
118 } | 118 } |
119 if (set_action_) { | 119 if (set_action_) { |
120 if (sigaction(SIGTERM, &old_action_, NULL) < 0) { | 120 if (sigaction(SIGTERM, &old_action_, NULL) < 0) { |
121 PLOG(ERROR) << "sigaction"; | 121 DPLOG(ERROR) << "sigaction"; |
122 } | 122 } |
123 } | 123 } |
124 g_signal_socket = -1; | 124 g_signal_socket = -1; |
125 } | 125 } |
126 | 126 |
127 void ServiceProcessState::CreateState() { | 127 void ServiceProcessState::CreateState() { |
128 CHECK(!state_); | 128 DCHECK(!state_); |
129 state_ = new StateData; | 129 state_ = new StateData; |
130 | 130 |
131 // Explicitly adding a reference here (and removing it in TearDownState) | 131 // Explicitly adding a reference here (and removing it in TearDownState) |
132 // because StateData is refcounted on Mac and Linux so that methods can | 132 // because StateData is refcounted on Mac and Linux so that methods can |
133 // be called on other threads. | 133 // be called on other threads. |
134 // It is not refcounted on Windows at this time. | 134 // It is not refcounted on Windows at this time. |
135 state_->AddRef(); | 135 state_->AddRef(); |
136 } | 136 } |
137 | 137 |
138 bool ServiceProcessState::SignalReady( | 138 bool ServiceProcessState::SignalReady( |
139 base::MessageLoopProxy* message_loop_proxy, Task* terminate_task) { | 139 base::MessageLoopProxy* message_loop_proxy, Task* terminate_task) { |
140 CHECK(state_); | 140 DCHECK(state_); |
141 | 141 |
142 scoped_ptr<Task> scoped_terminate_task(terminate_task); | 142 scoped_ptr<Task> scoped_terminate_task(terminate_task); |
143 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 143 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
144 state_->running_lock_.reset(TakeServiceRunningLock(true)); | 144 state_->running_lock_.reset(TakeServiceRunningLock(true)); |
145 if (state_->running_lock_.get() == NULL) { | 145 if (state_->running_lock_.get() == NULL) { |
146 return false; | 146 return false; |
147 } | 147 } |
148 #endif | 148 #endif |
149 state_->terminate_monitor_.reset( | 149 state_->terminate_monitor_.reset( |
150 new ServiceProcessTerminateMonitor(scoped_terminate_task.release())); | 150 new ServiceProcessTerminateMonitor(scoped_terminate_task.release())); |
151 if (pipe(state_->sockets_) < 0) { | 151 if (pipe(state_->sockets_) < 0) { |
152 PLOG(ERROR) << "pipe"; | 152 DPLOG(ERROR) << "pipe"; |
153 return false; | 153 return false; |
154 } | 154 } |
155 base::WaitableEvent signal_ready(true, false); | 155 base::WaitableEvent signal_ready(true, false); |
156 bool success = false; | 156 bool success = false; |
157 | 157 |
158 message_loop_proxy->PostTask(FROM_HERE, | 158 message_loop_proxy->PostTask(FROM_HERE, |
159 NewRunnableMethod(state_, &ServiceProcessState::StateData::SignalReady, | 159 NewRunnableMethod(state_, &ServiceProcessState::StateData::SignalReady, |
160 &signal_ready, | 160 &signal_ready, |
161 &success)); | 161 &success)); |
162 signal_ready.Wait(); | 162 signal_ready.Wait(); |
163 return success; | 163 return success; |
164 } | 164 } |
165 | 165 |
166 void ServiceProcessState::TearDownState() { | 166 void ServiceProcessState::TearDownState() { |
167 if (state_) { | 167 if (state_) { |
168 state_->Release(); | 168 state_->Release(); |
169 state_ = NULL; | 169 state_ = NULL; |
170 } | 170 } |
171 } | 171 } |
OLD | NEW |