Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(183)

Side by Side Diff: chrome/common/service_process_util_posix.cc

Issue 7736002: Make the mac service process handling code clean itself up properly as far as launchd is concerned. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add launchd test Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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 }
OLDNEW
« no previous file with comments | « chrome/common/service_process_util_posix.h ('k') | chrome/common/service_process_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698