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