diff options
-rw-r--r-- | base/metrics/stats_table.cc | 168 | ||||
-rw-r--r-- | base/metrics/stats_table.h | 10 | ||||
-rw-r--r-- | components/nacl/common/nacl_helper_linux.h | 6 | ||||
-rw-r--r-- | components/nacl/zygote/nacl_fork_delegate_linux.cc | 11 | ||||
-rw-r--r-- | content/browser/child_process_launcher.cc | 31 | ||||
-rw-r--r-- | content/public/common/content_descriptors.h | 2 | ||||
-rw-r--r-- | ipc/ipc_descriptors.h | 4 |
7 files changed, 145 insertions, 87 deletions
diff --git a/base/metrics/stats_table.cc b/base/metrics/stats_table.cc index 403e28c..716b7cf 100644 --- a/base/metrics/stats_table.cc +++ b/base/metrics/stats_table.cc @@ -15,7 +15,9 @@ #include "base/threading/thread_local_storage.h" #if defined(OS_POSIX) +#include "base/posix/global_descriptors.h" #include "errno.h" +#include "ipc/ipc_descriptors.h" #endif namespace base { @@ -88,10 +90,10 @@ inline int AlignedSize(int size) { } // namespace -// The StatsTable::Private maintains convenience pointers into the +// The StatsTable::Internal maintains convenience pointers into the // shared memory segment. Use this class to keep the data structure // clean and accessible. -class StatsTable::Private { +class StatsTable::Internal { public: // Various header information contained in the memory mapped segment. struct TableHeader { @@ -101,12 +103,14 @@ class StatsTable::Private { int max_threads; }; - // Construct a new Private based on expected size parameters, or + // Construct a new Internal based on expected size parameters, or // return NULL on failure. - static Private* New(const std::string& name, int size, - int max_threads, int max_counters); + static Internal* New(const std::string& name, + int size, + int max_threads, + int max_counters); - SharedMemory* shared_memory() { return &shared_memory_; } + SharedMemory* shared_memory() { return shared_memory_.get(); } // Accessors for our header pointers TableHeader* table_header() const { return table_header_; } @@ -136,8 +140,9 @@ class StatsTable::Private { private: // Constructor is private because you should use New() instead. - Private() - : table_header_(NULL), + explicit Internal(SharedMemory* shared_memory) + : shared_memory_(shared_memory), + table_header_(NULL), thread_names_table_(NULL), thread_tid_table_(NULL), thread_pid_table_(NULL), @@ -145,6 +150,10 @@ class StatsTable::Private { data_table_(NULL) { } + // Create or open the SharedMemory used by the stats table. + static SharedMemory* CreateSharedMemory(const std::string& name, + int size); + // Initializes the table on first access. Sets header values // appropriately and zeroes all counters. void InitializeTable(void* memory, int size, int max_counters, @@ -153,41 +162,68 @@ class StatsTable::Private { // Initializes our in-memory pointers into a pre-created StatsTable. void ComputeMappedPointers(void* memory); - SharedMemory shared_memory_; + scoped_ptr<SharedMemory> shared_memory_; TableHeader* table_header_; char* thread_names_table_; PlatformThreadId* thread_tid_table_; int* thread_pid_table_; char* counter_names_table_; int* data_table_; + + DISALLOW_COPY_AND_ASSIGN(Internal); }; // static -StatsTable::Private* StatsTable::Private::New(const std::string& name, - int size, - int max_threads, - int max_counters) { - scoped_ptr<Private> priv(new Private()); - if (!priv->shared_memory_.CreateNamed(name, true, size)) +StatsTable::Internal* StatsTable::Internal::New(const std::string& name, + int size, + int max_threads, + int max_counters) { + scoped_ptr<SharedMemory> shared_memory(CreateSharedMemory(name, size)); + if (!shared_memory.get()) return NULL; - if (!priv->shared_memory_.Map(size)) + if (!shared_memory->Map(size)) return NULL; - void* memory = priv->shared_memory_.memory(); + void* memory = shared_memory->memory(); + scoped_ptr<Internal> internal(new Internal(shared_memory.release())); TableHeader* header = static_cast<TableHeader*>(memory); // If the version does not match, then assume the table needs // to be initialized. if (header->version != kTableVersion) - priv->InitializeTable(memory, size, max_counters, max_threads); + internal->InitializeTable(memory, size, max_counters, max_threads); // We have a valid table, so compute our pointers. - priv->ComputeMappedPointers(memory); + internal->ComputeMappedPointers(memory); + + return internal.release(); +} - return priv.release(); +// static +SharedMemory* StatsTable::Internal::CreateSharedMemory(const std::string& name, + int size) { +#if defined(OS_POSIX) + GlobalDescriptors* global_descriptors = GlobalDescriptors::GetInstance(); + if (global_descriptors->MaybeGet(kStatsTableSharedMemFd) != -1) { + // Open the shared memory file descriptor passed by the browser process. + FileDescriptor file_descriptor( + global_descriptors->Get(kStatsTableSharedMemFd), false); + return new SharedMemory(file_descriptor, false); + } + // Otherwise we need to create it. + scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); + if (!shared_memory->CreateAnonymous(size)) + return NULL; + return shared_memory.release(); +#elif defined(OS_WIN) + scoped_ptr<SharedMemory> shared_memory(new SharedMemory()); + if (!shared_memory->CreateNamed(name, true, size)) + return NULL; + return shared_memory.release(); +#endif } -void StatsTable::Private::InitializeTable(void* memory, int size, +void StatsTable::Internal::InitializeTable(void* memory, int size, int max_counters, int max_threads) { // Zero everything. @@ -201,7 +237,7 @@ void StatsTable::Private::InitializeTable(void* memory, int size, header->max_threads = max_threads; } -void StatsTable::Private::ComputeMappedPointers(void* memory) { +void StatsTable::Internal::ComputeMappedPointers(void* memory) { char* data = static_cast<char*>(memory); int offset = 0; @@ -252,19 +288,19 @@ StatsTable* global_table = NULL; StatsTable::StatsTable(const std::string& name, int max_threads, int max_counters) - : impl_(NULL), + : internal_(NULL), tls_index_(SlotReturnFunction) { int table_size = - AlignedSize(sizeof(Private::TableHeader)) + + AlignedSize(sizeof(Internal::TableHeader)) + AlignedSize((max_counters * sizeof(char) * kMaxCounterNameLength)) + AlignedSize((max_threads * sizeof(char) * kMaxThreadNameLength)) + AlignedSize(max_threads * sizeof(int)) + AlignedSize(max_threads * sizeof(int)) + AlignedSize((sizeof(int) * (max_counters * max_threads))); - impl_ = Private::New(name, table_size, max_threads, max_counters); + internal_ = Internal::New(name, table_size, max_threads, max_counters); - if (!impl_) + if (!internal_) DPLOG(ERROR) << "StatsTable did not initialize"; } @@ -278,7 +314,7 @@ StatsTable::~StatsTable() { tls_index_.Free(); // Cleanup our shared memory. - delete impl_; + delete internal_; // If we are the global table, unregister ourselves. if (global_table == this) @@ -302,14 +338,14 @@ int StatsTable::GetSlot() const { int StatsTable::RegisterThread(const std::string& name) { int slot = 0; - if (!impl_) + if (!internal_) return 0; // Registering a thread requires that we lock the shared memory // so that two threads don't grab the same slot. Fortunately, // thread creation shouldn't happen in inner loops. { - SharedMemoryAutoLock lock(impl_->shared_memory()); + SharedMemoryAutoLock lock(internal_->shared_memory()); slot = FindEmptyThread(); if (!slot) { return 0; @@ -319,10 +355,10 @@ int StatsTable::RegisterThread(const std::string& name) { std::string thread_name = name; if (name.empty()) thread_name = kUnknownName; - strlcpy(impl_->thread_name(slot), thread_name.c_str(), + strlcpy(internal_->thread_name(slot), thread_name.c_str(), kMaxThreadNameLength); - *(impl_->thread_tid(slot)) = PlatformThread::CurrentId(); - *(impl_->thread_pid(slot)) = GetCurrentProcId(); + *(internal_->thread_tid(slot)) = PlatformThread::CurrentId(); + *(internal_->thread_pid(slot)) = GetCurrentProcId(); } // Set our thread local storage. @@ -334,14 +370,14 @@ int StatsTable::RegisterThread(const std::string& name) { } int StatsTable::CountThreadsRegistered() const { - if (!impl_) + if (!internal_) return 0; // Loop through the shared memory and count the threads that are active. // We intentionally do not lock the table during the operation. int count = 0; - for (int index = 1; index <= impl_->max_threads(); index++) { - char* name = impl_->thread_name(index); + for (int index = 1; index <= internal_->max_threads(); index++) { + char* name = internal_->thread_name(index); if (*name != '\0') count++; } @@ -352,7 +388,7 @@ int StatsTable::FindCounter(const std::string& name) { // Note: the API returns counters numbered from 1..N, although // internally, the array is 0..N-1. This is so that we can return // zero as "not found". - if (!impl_) + if (!internal_) return 0; // Create a scope for our auto-lock. @@ -371,20 +407,20 @@ int StatsTable::FindCounter(const std::string& name) { } int* StatsTable::GetLocation(int counter_id, int slot_id) const { - if (!impl_) + if (!internal_) return NULL; - if (slot_id > impl_->max_threads()) + if (slot_id > internal_->max_threads()) return NULL; - int* row = impl_->row(counter_id); + int* row = internal_->row(counter_id); return &(row[slot_id-1]); } const char* StatsTable::GetRowName(int index) const { - if (!impl_) + if (!internal_) return NULL; - return impl_->counter_name(index); + return internal_->counter_name(index); } int StatsTable::GetRowValue(int index) const { @@ -392,13 +428,13 @@ int StatsTable::GetRowValue(int index) const { } int StatsTable::GetRowValue(int index, int pid) const { - if (!impl_) + if (!internal_) return 0; int rv = 0; - int* row = impl_->row(index); - for (int slot_id = 1; slot_id <= impl_->max_threads(); slot_id++) { - if (pid == 0 || *impl_->thread_pid(slot_id) == pid) + int* row = internal_->row(index); + for (int slot_id = 1; slot_id <= internal_->max_threads(); slot_id++) { + if (pid == 0 || *internal_->thread_pid(slot_id) == pid) rv += row[slot_id-1]; } return rv; @@ -409,7 +445,7 @@ int StatsTable::GetCounterValue(const std::string& name) { } int StatsTable::GetCounterValue(const std::string& name, int pid) { - if (!impl_) + if (!internal_) return 0; int row = FindCounter(name); @@ -419,15 +455,15 @@ int StatsTable::GetCounterValue(const std::string& name, int pid) { } int StatsTable::GetMaxCounters() const { - if (!impl_) + if (!internal_) return 0; - return impl_->max_counters(); + return internal_->max_counters(); } int StatsTable::GetMaxThreads() const { - if (!impl_) + if (!internal_) return 0; - return impl_->max_threads(); + return internal_->max_threads(); } int* StatsTable::FindLocation(const char* name) { @@ -457,10 +493,10 @@ void StatsTable::UnregisterThread() { void StatsTable::UnregisterThread(TLSData* data) { if (!data) return; - DCHECK(impl_); + DCHECK(internal_); // Mark the slot free by zeroing out the thread name. - char* name = impl_->thread_name(data->slot); + char* name = internal_->thread_name(data->slot); *name = '\0'; // Remove the calling thread's TLS so that it cannot use the slot. @@ -488,16 +524,16 @@ int StatsTable::FindEmptyThread() const { // in TLS, which is always initialized to zero, not -1. If 0 were // returned as a valid slot number, it would be confused with the // uninitialized state. - if (!impl_) + if (!internal_) return 0; int index = 1; - for (; index <= impl_->max_threads(); index++) { - char* name = impl_->thread_name(index); + for (; index <= internal_->max_threads(); index++) { + char* name = internal_->thread_name(index); if (!*name) break; } - if (index > impl_->max_threads()) + if (index > internal_->max_threads()) return 0; // The table is full. return index; } @@ -510,12 +546,12 @@ int StatsTable::FindCounterOrEmptyRow(const std::string& name) const { // There isn't much reason for this other than to be consistent // with the way we track columns for thread slots. (See comments // in FindEmptyThread for why it is done this way). - if (!impl_) + if (!internal_) return 0; int free_slot = 0; - for (int index = 1; index <= impl_->max_counters(); index++) { - char* row_name = impl_->counter_name(index); + for (int index = 1; index <= internal_->max_counters(); index++) { + char* row_name = internal_->counter_name(index); if (!*row_name && !free_slot) free_slot = index; // save that we found a free slot else if (!strncmp(row_name, name.c_str(), kMaxCounterNameLength)) @@ -525,14 +561,14 @@ int StatsTable::FindCounterOrEmptyRow(const std::string& name) const { } int StatsTable::AddCounter(const std::string& name) { - if (!impl_) + if (!internal_) return 0; int counter_id = 0; { // To add a counter to the shared memory, we need the // shared memory lock. - SharedMemoryAutoLock lock(impl_->shared_memory()); + SharedMemoryAutoLock lock(internal_->shared_memory()); // We have space, so create a new counter. counter_id = FindCounterOrEmptyRow(name); @@ -542,7 +578,7 @@ int StatsTable::AddCounter(const std::string& name) { std::string counter_name = name; if (name.empty()) counter_name = kUnknownName; - strlcpy(impl_->counter_name(counter_id), counter_name.c_str(), + strlcpy(internal_->counter_name(counter_id), counter_name.c_str(), kMaxCounterNameLength); } @@ -565,4 +601,12 @@ StatsTable::TLSData* StatsTable::GetTLSData() const { return data; } +#if defined(OS_POSIX) +SharedMemoryHandle StatsTable::GetSharedMemoryHandle() const { + if (!internal_) + return SharedMemory::NULLHandle(); + return internal_->shared_memory()->handle(); +} +#endif + } // namespace base diff --git a/base/metrics/stats_table.h b/base/metrics/stats_table.h index 153af38..49ba79f 100644 --- a/base/metrics/stats_table.h +++ b/base/metrics/stats_table.h @@ -25,6 +25,7 @@ #include "base/base_export.h" #include "base/basictypes.h" #include "base/containers/hash_tables.h" +#include "base/memory/shared_memory.h" #include "base/synchronization/lock.h" #include "base/threading/thread_local_storage.h" @@ -116,6 +117,11 @@ class BASE_EXPORT StatsTable { // The maxinum number of threads/columns in the table. int GetMaxThreads() const; +#if defined(OS_POSIX) + // Get the underlying shared memory handle for the table. + base::SharedMemoryHandle GetSharedMemoryHandle() const; +#endif + // The maximum length (in characters) of a Thread's name including // null terminator, as stored in the shared memory. static const int kMaxThreadNameLength = 32; @@ -130,7 +136,7 @@ class BASE_EXPORT StatsTable { static int* FindLocation(const char *name); private: - class Private; + class Internal; struct TLSData; typedef hash_map<std::string, int> CountersMap; @@ -172,7 +178,7 @@ class BASE_EXPORT StatsTable { // initialized. TLSData* GetTLSData() const; - Private* impl_; + Internal* internal_; // The counters_lock_ protects the counters_ hash table. base::Lock counters_lock_; diff --git a/components/nacl/common/nacl_helper_linux.h b/components/nacl/common/nacl_helper_linux.h index d55ba1f..142964f 100644 --- a/components/nacl/common/nacl_helper_linux.h +++ b/components/nacl/common/nacl_helper_linux.h @@ -26,11 +26,5 @@ enum NaClZygoteIPCCommand { // For communications between NaCl loader and zygote. #define kNaClZygoteDescriptor 3 -// For communications between the NaCl loader process and -// the SUID sandbox. -#define kNaClSandboxDescriptor 5 -// NOTE: kNaClSandboxDescriptor must match -// content/browser/zygote_main_linux.cc -// kMagicSandboxIPCDescriptor. #endif // COMPONENTS_NACL_COMMON_NACL_HELPER_LINUX_H_ diff --git a/components/nacl/zygote/nacl_fork_delegate_linux.cc b/components/nacl/zygote/nacl_fork_delegate_linux.cc index 2a7e007..7bd2e9f 100644 --- a/components/nacl/zygote/nacl_fork_delegate_linux.cc +++ b/components/nacl/zygote/nacl_fork_delegate_linux.cc @@ -19,6 +19,7 @@ #include "base/path_service.h" #include "base/pickle.h" #include "base/posix/eintr_wrapper.h" +#include "base/posix/global_descriptors.h" #include "base/posix/unix_domain_socket_linux.h" #include "base/process/kill.h" #include "base/process/launch.h" @@ -26,6 +27,7 @@ #include "components/nacl/common/nacl_helper_linux.h" #include "components/nacl/common/nacl_paths.h" #include "components/nacl/common/nacl_switches.h" +#include "content/public/common/content_descriptors.h" #include "content/public/common/content_switches.h" namespace { @@ -110,14 +112,17 @@ void NaClForkDelegate::Init(const int sandboxdesc) { VLOG(1) << "NaClForkDelegate::Init()"; int fds[2]; + // For communications between the NaCl loader process and + // the SUID sandbox. + int nacl_sandbox_descriptor = + base::GlobalDescriptors::kBaseDescriptor + kSandboxIPCChannel; // Confirm a hard-wired assumption. - // The NaCl constant is from chrome/nacl/nacl_linux_helper.h - DCHECK(kNaClSandboxDescriptor == sandboxdesc); + DCHECK_EQ(sandboxdesc, nacl_sandbox_descriptor); CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); base::FileHandleMappingVector fds_to_map; fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor)); - fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor)); + fds_to_map.push_back(std::make_pair(sandboxdesc, nacl_sandbox_descriptor)); // Using nacl_helper_bootstrap is not necessary on x86-64 because // NaCl's x86-64 sandbox is not zero-address-based. Starting diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index 721cd5a..3b95c14 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc @@ -32,6 +32,7 @@ #include "base/android/jni_android.h" #include "content/browser/android/child_process_launcher_android.h" #elif defined(OS_POSIX) +#include "base/memory/shared_memory.h" #include "base/memory/singleton.h" #include "content/browser/renderer_host/render_sandbox_host_linux.h" #include "content/browser/zygote_host/zygote_host_impl_linux.h" @@ -39,6 +40,7 @@ #endif #if defined(OS_POSIX) +#include "base/metrics/stats_table.h" #include "base/posix/global_descriptors.h" #endif @@ -197,17 +199,27 @@ class ChildProcessLauncher::Context #if defined(OS_WIN) scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line); -#elif defined(OS_ANDROID) - // Android WebView runs in single process, ensure that we never get here - // when running in single process mode. - CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); - +#elif defined(OS_POSIX) std::string process_type = cmd_line->GetSwitchValueASCII(switches::kProcessType); std::vector<FileDescriptorInfo> files_to_register; files_to_register.push_back( FileDescriptorInfo(kPrimaryIPCChannel, - base::FileDescriptor(ipcfd, false))); + base::FileDescriptor(ipcfd, false))); + base::StatsTable* stats_table = base::StatsTable::current(); + if (stats_table && + base::SharedMemory::IsHandleValid( + stats_table->GetSharedMemoryHandle())) { + files_to_register.push_back( + FileDescriptorInfo(kStatsTableSharedMemFd, + stats_table->GetSharedMemoryHandle())); + } +#endif + +#if defined(OS_ANDROID) + // Android WebView runs in single process, ensure that we never get here + // when running in single process mode. + CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); GetContentClient()->browser()-> GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, @@ -223,13 +235,6 @@ class ChildProcessLauncher::Context // child termination. file_util::ScopedFD ipcfd_closer(&ipcfd); - std::string process_type = - cmd_line->GetSwitchValueASCII(switches::kProcessType); - std::vector<FileDescriptorInfo> files_to_register; - files_to_register.push_back( - FileDescriptorInfo(kPrimaryIPCChannel, - base::FileDescriptor(ipcfd, false))); - #if !defined(OS_MACOSX) GetContentClient()->browser()-> GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, diff --git a/content/public/common/content_descriptors.h b/content/public/common/content_descriptors.h index 3640ea5..ce7ab0e 100644 --- a/content/public/common/content_descriptors.h +++ b/content/public/common/content_descriptors.h @@ -10,7 +10,7 @@ // This is a list of global descriptor keys to be used with the // base::GlobalDescriptors object (see base/posix/global_descriptors.h) enum { - kCrashDumpSignal = kPrimaryIPCChannel + 1, + kCrashDumpSignal = kIPCDescriptorMax, kSandboxIPCChannel, // http://code.google.com/p/chromium/LinuxSandboxIPC #if defined(OS_ANDROID) diff --git a/ipc/ipc_descriptors.h b/ipc/ipc_descriptors.h index b766bbb..9dcff8c 100644 --- a/ipc/ipc_descriptors.h +++ b/ipc/ipc_descriptors.h @@ -9,6 +9,10 @@ // base::GlobalDescriptors object (see base/posix/global_descriptors.h) enum { kPrimaryIPCChannel = 0, + kStatsTableSharedMemFd, + + // The first key that can be use to register descriptors. + kIPCDescriptorMax }; #endif // IPC_IPC_DESCRIPTORS_H_ |