15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chrome_browser_main_posix.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <limits.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <signal.h>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/resource.h>
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/lifetime/application_lifetime.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/sessions/session_restore.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_observer.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_registrar.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/notification_service.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See comment in |PreEarlyInitialization()|, where sigaction is called.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SIGCHLDHandler(int signal) {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The OSX fork() implementation can crash in the child process before
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// fork() returns.  In that case, the shutdown pipe will still be
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// shared with the parent process.  To prevent child crashes from
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// causing parent shutdowns, |g_pipe_pid| is the pid for the process
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// which registered |g_shutdown_pipe_write_fd|.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// See <http://crbug.com/175341>.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)pid_t g_pipe_pid = -1;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int g_shutdown_pipe_write_fd = -1;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int g_shutdown_pipe_read_fd = -1;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Common code between SIG{HUP, INT, TERM}Handler.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GracefulShutdownHandler(int signal) {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reinstall the default handler.  We had one shot at graceful shutdown.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sigaction action;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&action, 0, sizeof(action));
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action.sa_handler = SIG_DFL;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(sigaction(signal, &action, NULL) == 0);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RAW_CHECK(g_pipe_pid == getpid());
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(g_shutdown_pipe_write_fd != -1);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(g_shutdown_pipe_read_fd != -1);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_written = 0;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = HANDLE_EINTR(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        write(g_shutdown_pipe_write_fd,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              reinterpret_cast<const char*>(&signal) + bytes_written,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              sizeof(signal) - bytes_written));
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_CHECK(rv >= 0);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_written += rv;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (bytes_written < sizeof(signal));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SIGHUPHandler(int signal) {
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(signal == SIGHUP);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GracefulShutdownHandler(signal);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SIGINTHandler(int signal) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(signal == SIGINT);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GracefulShutdownHandler(signal);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SIGTERMHandler(int signal) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(signal == SIGTERM);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GracefulShutdownHandler(signal);
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ExitHandler takes care of servicing an exit (from a signal) at the
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// appropriate time. Specifically if we get an exit and have not finished
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// session restore we delay the exit. To do otherwise means we're exiting part
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// way through startup which causes all sorts of problems.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ExitHandler : public content::NotificationObserver {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invokes exit when appropriate.
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void ExitWhenPossibleOnUIThread();
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Overridden from content::NotificationObserver:
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Observe(int type,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const content::NotificationSource& source,
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const content::NotificationDetails& details) OVERRIDE;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ExitHandler();
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ExitHandler();
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Does the appropriate call to Exit.
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void Exit();
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  content::NotificationRegistrar registrar_;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ExitHandler);
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExitHandler::ExitWhenPossibleOnUIThread() {
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (SessionRestore::IsRestoringSynchronously()) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ExitHandler takes care of deleting itself.
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    new ExitHandler();
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Exit();
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExitHandler::Observe(int type,
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const content::NotificationSource& source,
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          const content::NotificationDetails& details) {
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!SessionRestore::IsRestoringSynchronously()) {
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // At this point the message loop may not be running (meaning we haven't
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // gotten through browser startup, but are close). Post the task to at which
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // point the message loop is running.
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            base::Bind(&ExitHandler::Exit));
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete this;
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExitHandler::ExitHandler() {
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  registrar_.Add(
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      this, chrome::NOTIFICATION_SESSION_RESTORE_DONE,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::NotificationService::AllBrowserContextsAndSources());
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ExitHandler::~ExitHandler() {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ExitHandler::Exit() {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_CHROMEOS)
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // On ChromeOS, exiting on signal should be always clean.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::ExitCleanly();
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  chrome::AttemptExit();
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ShutdownDetector : public base::PlatformThread::Delegate {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ShutdownDetector(int shutdown_fd);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ThreadMain() OVERRIDE;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int shutdown_fd_;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ShutdownDetector::ShutdownDetector(int shutdown_fd)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : shutdown_fd_(shutdown_fd) {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_NE(shutdown_fd_, -1);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions are used to help us diagnose crash dumps that happen
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// during the shutdown process.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NOINLINE void ShutdownFDReadError() {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure function isn't optimized away.
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  asm("");
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(UINT_MAX);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NOINLINE void ShutdownFDClosedError() {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure function isn't optimized away.
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  asm("");
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(UINT_MAX);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NOINLINE void ExitPosted() {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure function isn't optimized away.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  asm("");
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(UINT_MAX);
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShutdownDetector::ThreadMain() {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::SetName("CrShutdownDetector");
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int signal;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t bytes_read = 0;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssize_t ret;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ret = HANDLE_EINTR(
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        read(shutdown_fd_,
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             reinterpret_cast<char*>(&signal) + bytes_read,
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             sizeof(signal) - bytes_read));
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ret < 0) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected error: " << strerror(errno);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShutdownFDReadError();
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (ret == 0) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected closure of shutdown pipe.";
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ShutdownFDClosedError();
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bytes_read += ret;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (bytes_read < sizeof(signal));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Handling shutdown for signal " << signal << ".";
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure task = base::Bind(&ExitHandler::ExitWhenPossibleOnUIThread);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Without a UI thread to post the exit task to, there aren't many
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // options.  Raise the signal again.  The default handler will pick it up
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and cause an ungraceful exit.
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_LOG(WARNING, "No UI thread, exiting ungracefully.");
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kill(getpid(), signal);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The signal may be handled on another thread.  Give that a chance to
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // happen.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sleep(3);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We really should be dead by now.  For whatever reason, we're not. Exit
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // immediately, with the exit status set to the signal number with bit 8
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // set.  On the systems that we care about, this exit status is what is
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // normally used to indicate an exit by this signal's default handler.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This mechanism isn't a de jure standard, but even in the worst case, it
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // should at least result in an immediate exit.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_LOG(WARNING, "Still here, exiting really ungracefully.");
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    _exit(signal | (1 << 7));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExitPosted();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ChromeBrowserMainPartsPosix -------------------------------------------------
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeBrowserMainPartsPosix::ChromeBrowserMainPartsPosix(
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const content::MainFunctionParams& parameters)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ChromeBrowserMainParts(parameters) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeBrowserMainPartsPosix::PreEarlyInitialization() {
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChromeBrowserMainParts::PreEarlyInitialization();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to accept SIGCHLD, even though our handler is a no-op because
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // otherwise we cannot wait on children. (According to POSIX 2001.)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sigaction action;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&action, 0, sizeof(action));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action.sa_handler = SIGCHLDHandler;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(sigaction(SIGCHLD, &action, NULL) == 0);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeBrowserMainPartsPosix::PostMainMessageLoopStart() {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChromeBrowserMainParts::PostMainMessageLoopStart();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pipefd[2];
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = pipe(pipefd);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ret < 0) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PLOG(DFATAL) << "Failed to create pipe";
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    g_pipe_pid = getpid();
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_shutdown_pipe_read_fd = pipefd[0];
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_shutdown_pipe_write_fd = pipefd[1];
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(ADDRESS_SANITIZER) && !defined(KEEP_SHADOW_STACKS)
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // ASan instrumentation and -finstrument-functions (used for keeping the
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // shadow stacks) bloat the stack frames, so we need to increase the stack
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // size to avoid hitting the guard page.
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if you change this, you'll probably need to change the suppression.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!base::PlatformThread::CreateNonJoinable(
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            kShutdownDetectorThreadStackSize,
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            new ShutdownDetector(g_shutdown_pipe_read_fd))) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG(DFATAL) << "Failed to create shutdown detector task.";
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Setup signal handlers for shutdown AFTER shutdown pipe is setup because
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it may be called right away after handler is set.
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If adding to this list of signal handlers, note the new signal probably
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // needs to be reset in child processes. See
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base/process_util_posix.cc:LaunchProcess.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to handle SIGTERM, because that is how many POSIX-based distros ask
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // processes to quit gracefully at shutdown time.
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct sigaction action;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(&action, 0, sizeof(action));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action.sa_handler = SIGTERMHandler;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(sigaction(SIGTERM, &action, NULL) == 0);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the browser process is being debugged, GDB will catch the SIGINT first.
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action.sa_handler = SIGINTHandler;
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(sigaction(SIGINT, &action, NULL) == 0);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // And SIGHUP, for when the terminal disappears. On shutdown, many Linux
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // distros send SIGHUP, SIGTERM, and then SIGKILL.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  action.sa_handler = SIGHUPHandler;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(sigaction(SIGHUP, &action, NULL) == 0);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChromeBrowserMainPartsPosix::ShowMissingLocaleMessageBox() {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_CHROMEOS)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();  // Should not ever happen on ChromeOS.
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_MACOSX)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Not called on Mac because we load the locale files differently.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(USE_AURA)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(port): We may want a views based message dialog here eventually, but
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // for now, crash.
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#error "Need MessageBox implementation."
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
326