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
3 // found in the LICENSE file.
5 #include "chrome/browser/chrome_browser_main_posix.h"
11 #include <sys/resource.h>
16 #include "base/bind.h"
17 #include "base/command_line.h"
18 #include "base/logging.h"
19 #include "base/posix/eintr_wrapper.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/lifetime/application_lifetime.h"
23 #include "chrome/browser/sessions/session_restore.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/notification_observer.h"
27 #include "content/public/browser/notification_registrar.h"
28 #include "content/public/browser/notification_service.h"
30 using content::BrowserThread
;
34 // See comment in |PreEarlyInitialization()|, where sigaction is called.
35 void SIGCHLDHandler(int signal
) {
38 // The OSX fork() implementation can crash in the child process before
39 // fork() returns. In that case, the shutdown pipe will still be
40 // shared with the parent process. To prevent child crashes from
41 // causing parent shutdowns, |g_pipe_pid| is the pid for the process
42 // which registered |g_shutdown_pipe_write_fd|.
43 // See <http://crbug.com/175341>.
44 pid_t g_pipe_pid
= -1;
45 int g_shutdown_pipe_write_fd
= -1;
46 int g_shutdown_pipe_read_fd
= -1;
48 // Common code between SIG{HUP, INT, TERM}Handler.
49 void GracefulShutdownHandler(int signal
) {
50 // Reinstall the default handler. We had one shot at graceful shutdown.
51 struct sigaction action
;
52 memset(&action
, 0, sizeof(action
));
53 action
.sa_handler
= SIG_DFL
;
54 RAW_CHECK(sigaction(signal
, &action
, NULL
) == 0);
56 RAW_CHECK(g_pipe_pid
== getpid());
57 RAW_CHECK(g_shutdown_pipe_write_fd
!= -1);
58 RAW_CHECK(g_shutdown_pipe_read_fd
!= -1);
59 size_t bytes_written
= 0;
61 int rv
= HANDLE_EINTR(
62 write(g_shutdown_pipe_write_fd
,
63 reinterpret_cast<const char*>(&signal
) + bytes_written
,
64 sizeof(signal
) - bytes_written
));
67 } while (bytes_written
< sizeof(signal
));
70 // See comment in |PostMainMessageLoopStart()|, where sigaction is called.
71 void SIGHUPHandler(int signal
) {
72 RAW_CHECK(signal
== SIGHUP
);
73 GracefulShutdownHandler(signal
);
76 // See comment in |PostMainMessageLoopStart()|, where sigaction is called.
77 void SIGINTHandler(int signal
) {
78 RAW_CHECK(signal
== SIGINT
);
79 GracefulShutdownHandler(signal
);
82 // See comment in |PostMainMessageLoopStart()|, where sigaction is called.
83 void SIGTERMHandler(int signal
) {
84 RAW_CHECK(signal
== SIGTERM
);
85 GracefulShutdownHandler(signal
);
88 // ExitHandler takes care of servicing an exit (from a signal) at the
89 // appropriate time. Specifically if we get an exit and have not finished
90 // session restore we delay the exit. To do otherwise means we're exiting part
91 // way through startup which causes all sorts of problems.
92 class ExitHandler
: public content::NotificationObserver
{
94 // Invokes exit when appropriate.
95 static void ExitWhenPossibleOnUIThread();
97 // Overridden from content::NotificationObserver:
98 void Observe(int type
,
99 const content::NotificationSource
& source
,
100 const content::NotificationDetails
& details
) override
;
104 ~ExitHandler() override
;
106 // Does the appropriate call to Exit.
109 content::NotificationRegistrar registrar_
;
111 DISALLOW_COPY_AND_ASSIGN(ExitHandler
);
115 void ExitHandler::ExitWhenPossibleOnUIThread() {
116 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
));
117 if (SessionRestore::IsRestoringSynchronously()) {
118 // ExitHandler takes care of deleting itself.
125 void ExitHandler::Observe(int type
,
126 const content::NotificationSource
& source
,
127 const content::NotificationDetails
& details
) {
128 if (!SessionRestore::IsRestoringSynchronously()) {
129 // At this point the message loop may not be running (meaning we haven't
130 // gotten through browser startup, but are close). Post the task to at which
131 // point the message loop is running.
132 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
133 base::Bind(&ExitHandler::Exit
));
138 ExitHandler::ExitHandler() {
140 this, chrome::NOTIFICATION_SESSION_RESTORE_DONE
,
141 content::NotificationService::AllBrowserContextsAndSources());
144 ExitHandler::~ExitHandler() {
148 void ExitHandler::Exit() {
149 #if defined(OS_CHROMEOS)
150 // On ChromeOS, exiting on signal should be always clean.
151 chrome::ExitCleanly();
153 chrome::AttemptExit();
157 class ShutdownDetector
: public base::PlatformThread::Delegate
{
159 explicit ShutdownDetector(int shutdown_fd
);
161 void ThreadMain() override
;
164 const int shutdown_fd_
;
166 DISALLOW_COPY_AND_ASSIGN(ShutdownDetector
);
169 ShutdownDetector::ShutdownDetector(int shutdown_fd
)
170 : shutdown_fd_(shutdown_fd
) {
171 CHECK_NE(shutdown_fd_
, -1);
174 // These functions are used to help us diagnose crash dumps that happen
175 // during the shutdown process.
176 NOINLINE
void ShutdownFDReadError() {
177 // Ensure function isn't optimized away.
182 NOINLINE
void ShutdownFDClosedError() {
183 // Ensure function isn't optimized away.
188 NOINLINE
void ExitPosted() {
189 // Ensure function isn't optimized away.
194 void ShutdownDetector::ThreadMain() {
195 base::PlatformThread::SetName("CrShutdownDetector");
198 size_t bytes_read
= 0;
203 reinterpret_cast<char*>(&signal
) + bytes_read
,
204 sizeof(signal
) - bytes_read
));
206 NOTREACHED() << "Unexpected error: " << strerror(errno
);
207 ShutdownFDReadError();
209 } else if (ret
== 0) {
210 NOTREACHED() << "Unexpected closure of shutdown pipe.";
211 ShutdownFDClosedError();
215 } while (bytes_read
< sizeof(signal
));
216 VLOG(1) << "Handling shutdown for signal " << signal
<< ".";
217 base::Closure task
= base::Bind(&ExitHandler::ExitWhenPossibleOnUIThread
);
219 if (!BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, task
)) {
220 // Without a UI thread to post the exit task to, there aren't many
221 // options. Raise the signal again. The default handler will pick it up
222 // and cause an ungraceful exit.
223 RAW_LOG(WARNING
, "No UI thread, exiting ungracefully.");
224 kill(getpid(), signal
);
226 // The signal may be handled on another thread. Give that a chance to
230 // We really should be dead by now. For whatever reason, we're not. Exit
231 // immediately, with the exit status set to the signal number with bit 8
232 // set. On the systems that we care about, this exit status is what is
233 // normally used to indicate an exit by this signal's default handler.
234 // This mechanism isn't a de jure standard, but even in the worst case, it
235 // should at least result in an immediate exit.
236 RAW_LOG(WARNING
, "Still here, exiting really ungracefully.");
237 _exit(signal
| (1 << 7));
244 // ChromeBrowserMainPartsPosix -------------------------------------------------
246 ChromeBrowserMainPartsPosix::ChromeBrowserMainPartsPosix(
247 const content::MainFunctionParams
& parameters
)
248 : ChromeBrowserMainParts(parameters
) {
251 void ChromeBrowserMainPartsPosix::PreEarlyInitialization() {
252 ChromeBrowserMainParts::PreEarlyInitialization();
254 // We need to accept SIGCHLD, even though our handler is a no-op because
255 // otherwise we cannot wait on children. (According to POSIX 2001.)
256 struct sigaction action
;
257 memset(&action
, 0, sizeof(action
));
258 action
.sa_handler
= SIGCHLDHandler
;
259 CHECK(sigaction(SIGCHLD
, &action
, NULL
) == 0);
262 void ChromeBrowserMainPartsPosix::PostMainMessageLoopStart() {
263 ChromeBrowserMainParts::PostMainMessageLoopStart();
266 int ret
= pipe(pipefd
);
268 PLOG(DFATAL
) << "Failed to create pipe";
270 g_pipe_pid
= getpid();
271 g_shutdown_pipe_read_fd
= pipefd
[0];
272 g_shutdown_pipe_write_fd
= pipefd
[1];
273 #if !defined(ADDRESS_SANITIZER) && !defined(KEEP_SHADOW_STACKS)
274 const size_t kShutdownDetectorThreadStackSize
= PTHREAD_STACK_MIN
* 2;
276 // ASan instrumentation and -finstrument-functions (used for keeping the
277 // shadow stacks) bloat the stack frames, so we need to increase the stack
278 // size to avoid hitting the guard page.
279 const size_t kShutdownDetectorThreadStackSize
= PTHREAD_STACK_MIN
* 4;
281 // TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
282 // if you change this, you'll probably need to change the suppression.
283 if (!base::PlatformThread::CreateNonJoinable(
284 kShutdownDetectorThreadStackSize
,
285 new ShutdownDetector(g_shutdown_pipe_read_fd
))) {
286 LOG(DFATAL
) << "Failed to create shutdown detector task.";
289 // Setup signal handlers for shutdown AFTER shutdown pipe is setup because
290 // it may be called right away after handler is set.
292 // If adding to this list of signal handlers, note the new signal probably
293 // needs to be reset in child processes. See
294 // base/process_util_posix.cc:LaunchProcess.
296 // We need to handle SIGTERM, because that is how many POSIX-based distros ask
297 // processes to quit gracefully at shutdown time.
298 struct sigaction action
;
299 memset(&action
, 0, sizeof(action
));
300 action
.sa_handler
= SIGTERMHandler
;
301 CHECK(sigaction(SIGTERM
, &action
, NULL
) == 0);
302 // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
303 // the browser process is being debugged, GDB will catch the SIGINT first.
304 action
.sa_handler
= SIGINTHandler
;
305 CHECK(sigaction(SIGINT
, &action
, NULL
) == 0);
306 // And SIGHUP, for when the terminal disappears. On shutdown, many Linux
307 // distros send SIGHUP, SIGTERM, and then SIGKILL.
308 action
.sa_handler
= SIGHUPHandler
;
309 CHECK(sigaction(SIGHUP
, &action
, NULL
) == 0);
312 void ChromeBrowserMainPartsPosix::ShowMissingLocaleMessageBox() {
313 #if defined(OS_CHROMEOS)
314 NOTREACHED(); // Should not ever happen on ChromeOS.
315 #elif defined(OS_MACOSX)
316 // Not called on Mac because we load the locale files differently.
318 #elif defined(USE_AURA)
319 // TODO(port): We may want a views based message dialog here eventually, but
323 #error "Need MessageBox implementation."