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

Side by Side Diff: chrome/nacl/nacl_fork_delegate_linux.cc

Issue 8342017: Add UMA reports for Linux nacl_helper startup status (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: review nits Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/common/nacl_fork_delegate_linux.h" 5 #include "chrome/common/nacl_fork_delegate_linux.h"
6 6
7 #include <signal.h> 7 #include <signal.h>
8 #include <stdlib.h> 8 #include <stdlib.h>
9 #include <sys/socket.h> 9 #include <sys/socket.h>
10 10
11 #include "base/basictypes.h" 11 #include "base/basictypes.h"
12 #include "base/command_line.h" 12 #include "base/command_line.h"
13 #include "base/eintr_wrapper.h" 13 #include "base/eintr_wrapper.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/file_path.h" 15 #include "base/file_path.h"
16 #include "base/path_service.h" 16 #include "base/path_service.h"
17 #include "base/process_util.h" 17 #include "base/process_util.h"
18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h" 18 #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
19 #include "content/common/unix_domain_socket_posix.h" 19 #include "content/common/unix_domain_socket_posix.h"
20 #include "content/common/zygote_fork_delegate_linux.h" 20 #include "content/common/zygote_fork_delegate_linux.h"
21 #include "chrome/common/chrome_paths.h" 21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/common/chrome_switches.h" 22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/nacl_helper_linux.h" 23 #include "chrome/common/nacl_helper_linux.h"
24 24
25 NaClForkDelegate::NaClForkDelegate() 25 NaClForkDelegate::NaClForkDelegate()
26 : ready_(false), 26 : status_(kNaClHelperUnused),
27 sandboxed_(false), 27 sandboxed_(false),
28 fd_(-1) {} 28 fd_(-1) {}
29 29
30 const char kNaClHelperAtZero[] = "--at-zero"; 30 const char kNaClHelperAtZero[] = "--at-zero";
31 31
32 void NaClForkDelegate::Init(const bool sandboxed, 32 void NaClForkDelegate::Init(const bool sandboxed,
33 const int browserdesc, 33 const int browserdesc,
34 const int sandboxdesc) { 34 const int sandboxdesc) {
35 VLOG(1) << "NaClForkDelegate::Init()"; 35 VLOG(1) << "NaClForkDelegate::Init()";
36 int fds[2]; 36 int fds[2];
37 37
38 sandboxed_ = sandboxed; 38 sandboxed_ = sandboxed;
39 // Confirm a couple hard-wired assumptions. 39 // Confirm a couple hard-wired assumptions.
40 // The NaCl constants are from chrome/nacl/nacl_linux_helper.h 40 // The NaCl constants are from chrome/nacl/nacl_linux_helper.h
41 DCHECK(kNaClBrowserDescriptor == browserdesc); 41 DCHECK(kNaClBrowserDescriptor == browserdesc);
42 DCHECK(kNaClSandboxDescriptor == sandboxdesc); 42 DCHECK(kNaClSandboxDescriptor == sandboxdesc);
43 43
44 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0); 44 CHECK(socketpair(PF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
45 base::file_handle_mapping_vector fds_to_map; 45 base::file_handle_mapping_vector fds_to_map;
46 fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor)); 46 fds_to_map.push_back(std::make_pair(fds[1], kNaClZygoteDescriptor));
47 fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor)); 47 fds_to_map.push_back(std::make_pair(sandboxdesc, kNaClSandboxDescriptor));
48 ready_ = false; 48
49 status_ = kNaClHelperUnused;
49 FilePath helper_exe; 50 FilePath helper_exe;
50 FilePath helper_bootstrap_exe; 51 FilePath helper_bootstrap_exe;
51 if (PathService::Get(chrome::FILE_NACL_HELPER, &helper_exe) && 52 if (!PathService::Get(chrome::FILE_NACL_HELPER, &helper_exe)) {
52 PathService::Get(chrome::FILE_NACL_HELPER_BOOTSTRAP, 53 status_ = kNaClHelperMissing;
53 &helper_bootstrap_exe) && 54 } else if (!PathService::Get(chrome::FILE_NACL_HELPER_BOOTSTRAP,
54 !RunningOnValgrind()) { 55 &helper_bootstrap_exe)) {
56 status_ = kNaClHelperBootstrapMissing;
57 } else if (RunningOnValgrind()) {
58 status_ = kNaClHelperValgrind;
59 } else {
55 CommandLine cmd_line(helper_bootstrap_exe); 60 CommandLine cmd_line(helper_bootstrap_exe);
56 cmd_line.AppendArgPath(helper_exe); 61 cmd_line.AppendArgPath(helper_exe);
57 cmd_line.AppendArgNative(kNaClHelperAtZero); 62 cmd_line.AppendArgNative(kNaClHelperAtZero);
58 base::LaunchOptions options; 63 base::LaunchOptions options;
59 options.fds_to_remap = &fds_to_map; 64 options.fds_to_remap = &fds_to_map;
60 options.clone_flags = CLONE_FS | SIGCHLD; 65 options.clone_flags = CLONE_FS | SIGCHLD;
61 ready_ = base::LaunchProcess(cmd_line.argv(), options, NULL); 66 if (!base::LaunchProcess(cmd_line.argv(), options, NULL))
67 status_ = kNaClHelperLaunchFailed;
62 // parent and error cases are handled below 68 // parent and error cases are handled below
63 } 69 }
64 if (HANDLE_EINTR(close(fds[1])) != 0) 70 if (HANDLE_EINTR(close(fds[1])) != 0)
65 LOG(ERROR) << "close(fds[1]) failed"; 71 LOG(ERROR) << "close(fds[1]) failed";
66 if (ready_) { 72 if (status_ == kNaClHelperUnused) {
67 const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck); 73 const ssize_t kExpectedLength = strlen(kNaClHelperStartupAck);
68 char buf[kExpectedLength]; 74 char buf[kExpectedLength];
69 75
70 // Wait for ack from nacl_helper, indicating it is ready to help 76 // Wait for ack from nacl_helper, indicating it is ready to help
71 const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf))); 77 const ssize_t nread = HANDLE_EINTR(read(fds[0], buf, sizeof(buf)));
72 if (nread == kExpectedLength && 78 if (nread == kExpectedLength &&
73 memcmp(buf, kNaClHelperStartupAck, nread) == 0) { 79 memcmp(buf, kNaClHelperStartupAck, nread) == 0) {
74 // all is well 80 // all is well
81 status_ = kNaClHelperSuccess;
75 fd_ = fds[0]; 82 fd_ = fds[0];
76 return; 83 return;
77 } 84 }
85
86 status_ = kNaClHelperAckFailed;
78 LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)"; 87 LOG(ERROR) << "Bad NaCl helper startup ack (" << nread << " bytes)";
79 } 88 }
80 // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper 89 // TODO(bradchen): Make this LOG(ERROR) when the NaCl helper
81 // becomes the default. 90 // becomes the default.
82 ready_ = false;
83 fd_ = -1; 91 fd_ = -1;
84 if (HANDLE_EINTR(close(fds[0])) != 0) 92 if (HANDLE_EINTR(close(fds[0])) != 0)
85 LOG(ERROR) << "close(fds[0]) failed"; 93 LOG(ERROR) << "close(fds[0]) failed";
86 } 94 }
87 95
96 void NaClForkDelegate::InitialUMA(std::string* uma_name,
97 int* uma_sample,
98 int* uma_boundary_value) {
99 *uma_name = "NaCl.Client.Helper.InitState";
100 *uma_sample = status_;
101 *uma_boundary_value = kNaClHelperStatusBoundary;
102 }
103
88 NaClForkDelegate::~NaClForkDelegate() { 104 NaClForkDelegate::~NaClForkDelegate() {
89 // side effect of close: delegate process will terminate 105 // side effect of close: delegate process will terminate
90 if (ready_) { 106 if (status_ == kNaClHelperSuccess) {
91 if (HANDLE_EINTR(close(fd_)) != 0) 107 if (HANDLE_EINTR(close(fd_)) != 0)
92 LOG(ERROR) << "close(fd_) failed"; 108 LOG(ERROR) << "close(fd_) failed";
93 } 109 }
94 } 110 }
95 111
96 bool NaClForkDelegate::CanHelp(const std::string& process_type) { 112 bool NaClForkDelegate::CanHelp(const std::string& process_type,
97 return (process_type == switches::kNaClLoaderProcess && ready_); 113 std::string* uma_name,
114 int* uma_sample,
115 int* uma_boundary_value) {
116 if (process_type != switches::kNaClLoaderProcess)
117 return false;
118 *uma_name = "NaCl.Client.Helper.StateOnFork";
119 *uma_sample = status_;
120 *uma_boundary_value = kNaClHelperStatusBoundary;
121 return status_ == kNaClHelperSuccess;
98 } 122 }
99 123
100 pid_t NaClForkDelegate::Fork(const std::vector<int>& fds) { 124 pid_t NaClForkDelegate::Fork(const std::vector<int>& fds) {
101 base::ProcessId naclchild; 125 base::ProcessId naclchild;
102 VLOG(1) << "NaClForkDelegate::Fork"; 126 VLOG(1) << "NaClForkDelegate::Fork";
103 127
104 DCHECK(fds.size() == kNaClParentFDIndex + 1); 128 DCHECK(fds.size() == kNaClParentFDIndex + 1);
105 if (!UnixDomainSocket::SendMsg(fd_, kNaClForkRequest, 129 if (!UnixDomainSocket::SendMsg(fd_, kNaClForkRequest,
106 strlen(kNaClForkRequest), fds)) { 130 strlen(kNaClForkRequest), fds)) {
107 LOG(ERROR) << "NaClForkDelegate::Fork: SendMsg failed"; 131 LOG(ERROR) << "NaClForkDelegate::Fork: SendMsg failed";
(...skipping 10 matching lines...) Expand all
118 142
119 bool NaClForkDelegate::AckChild(const int fd, 143 bool NaClForkDelegate::AckChild(const int fd,
120 const std::string& channel_switch) { 144 const std::string& channel_switch) {
121 int nwritten = HANDLE_EINTR(write(fd, channel_switch.c_str(), 145 int nwritten = HANDLE_EINTR(write(fd, channel_switch.c_str(),
122 channel_switch.length())); 146 channel_switch.length()));
123 if (nwritten != static_cast<int>(channel_switch.length())) { 147 if (nwritten != static_cast<int>(channel_switch.length())) {
124 return false; 148 return false;
125 } 149 }
126 return true; 150 return true;
127 } 151 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698