Index: chrome/browser/nacl_host/nacl_process_host.cc |
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc |
index ebf3bbfadd4b433a08ae1189c1eba12612b34f57..0ac0872173197cfd253cfe973215dd8173f3c73b 100644 |
--- a/chrome/browser/nacl_host/nacl_process_host.cc |
+++ b/chrome/browser/nacl_host/nacl_process_host.cc |
@@ -52,17 +52,21 @@ struct NaClProcessHost::NaClInternal { |
std::vector<nacl::Handle> sockets_for_sel_ldr; |
}; |
+bool NaClProcessHost::RunningOnWOW64() { |
+#if defined(OS_WIN) |
+ return (base::win::OSInfo::GetInstance()->wow64_status() == |
+ base::win::OSInfo::WOW64_ENABLED); |
+#else |
+ return false; |
+#endif |
+} |
+ |
NaClProcessHost::NaClProcessHost(const std::wstring& url) |
: BrowserChildProcessHost(NACL_LOADER_PROCESS), |
reply_msg_(NULL), |
internal_(new NaClInternal()), |
- running_on_wow64_(false), |
ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { |
set_name(WideToUTF16Hack(url)); |
-#if defined(OS_WIN) |
- running_on_wow64_ = (base::win::OSInfo::GetInstance()->wow64_status() == |
- base::win::OSInfo::WOW64_ENABLED); |
-#endif |
} |
NaClProcessHost::~NaClProcessHost() { |
@@ -105,6 +109,11 @@ bool NaClProcessHost::Launch( |
return false; |
} |
+ if (irt_platform_file_ == base::kInvalidPlatformFileValue) { |
+ LOG(ERROR) << "Cannot launch NaCl process after IRT file open failed"; |
+ return false; |
+ } |
+ |
// Rather than creating a socket pair in the renderer, and passing |
// one side through the browser to sel_ldr, socket pairs are created |
// in the browser and then passed to the renderer and sel_ldr. |
@@ -180,7 +189,7 @@ bool NaClProcessHost::LaunchSelLdr() { |
// On Windows we might need to start the broker process to launch a new loader |
#if defined(OS_WIN) |
- if (running_on_wow64_) { |
+ if (RunningOnWOW64()) { |
return NaClBrokerService::GetInstance()->LaunchLoader( |
this, ASCIIToWide(channel_id())); |
} else { |
@@ -202,7 +211,7 @@ void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) { |
base::TerminationStatus NaClProcessHost::GetChildTerminationStatus( |
int* exit_code) { |
- if (running_on_wow64_) |
+ if (RunningOnWOW64()) |
return base::GetTerminationStatus(handle(), exit_code); |
return BrowserChildProcessHost::GetChildTerminationStatus(exit_code); |
} |
@@ -225,25 +234,13 @@ void NaClProcessHost::OnChildDied() { |
BrowserChildProcessHost::OnChildDied(); |
} |
-FilePath::StringType NaClProcessHost::GetIrtLibraryFilename() { |
- bool on_x86_64 = running_on_wow64_; |
-#if defined(__x86_64__) |
- on_x86_64 = true; |
-#endif |
- if (on_x86_64) { |
- return FILE_PATH_LITERAL("nacl_irt_x86_64.nexe"); |
- } else { |
- return FILE_PATH_LITERAL("nacl_irt_x86_32.nexe"); |
- } |
-} |
+base::PlatformFile NaClProcessHost::irt_platform_file_; |
+ |
+void NaClProcessHost::OpenIrtLibraryFile() { |
+ irt_platform_file_ = base::kInvalidPlatformFileValue; |
+ |
+ FilePath irt_filepath; |
-void NaClProcessHost::OnProcessLaunched() { |
- // TODO(mseaborn): Opening the IRT file every time a NaCl process is |
- // launched probably does not work with auto-update on Linux. We |
- // might need to open the file on startup. If so, we would need to |
- // ensure that NaCl's ELF loader does not use lseek() on the shared |
- // IRT file descriptor, otherwise there would be a race condition. |
- FilePath irt_path; |
// Allow the IRT library to be overridden via an environment |
// variable. This allows the NaCl/Chromium integration bot to |
// specify a newly-built IRT rather than using a prebuilt one |
@@ -251,41 +248,80 @@ void NaClProcessHost::OnProcessLaunched() { |
// variable that the standalone NaCl PPAPI plugin accepts. |
const char* irt_path_var = getenv("NACL_IRT_LIBRARY"); |
if (irt_path_var != NULL) { |
- FilePath::StringType string(irt_path_var, |
- irt_path_var + strlen(irt_path_var)); |
- irt_path = FilePath(string); |
+ FilePath::StringType path_string( |
+ irt_path_var, const_cast<const char*>(strchr(irt_path_var, '\0'))); |
+ irt_filepath = FilePath(path_string); |
} else { |
FilePath plugin_dir; |
if (!PathService::Get(chrome::DIR_INTERNAL_PLUGINS, &plugin_dir)) { |
LOG(ERROR) << "Failed to locate the plugins directory"; |
- delete this; |
return; |
} |
- irt_path = plugin_dir.Append(GetIrtLibraryFilename()); |
+ |
+ bool on_x86_64 = RunningOnWOW64(); |
+#if defined(__x86_64__) |
+ on_x86_64 = true; |
+#endif |
+ FilePath::StringType irt_name; |
+ if (on_x86_64) { |
+ irt_name = FILE_PATH_LITERAL("nacl_irt_x86_64.nexe"); |
+ } else { |
+ irt_name = FILE_PATH_LITERAL("nacl_irt_x86_32.nexe"); |
+ } |
+ |
+ irt_filepath = plugin_dir.Append(irt_name); |
} |
- if (!base::FileUtilProxy::CreateOrOpen( |
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE), |
- irt_path, |
- base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, |
- base::Bind(&NaClProcessHost::OpenIrtFileDone, |
- weak_factory_.GetWeakPtr()))) { |
- delete this; |
+ base::PlatformFileError error_code; |
+ irt_platform_file_ = base::CreatePlatformFile(irt_filepath, |
+ base::PLATFORM_FILE_OPEN | |
+ base::PLATFORM_FILE_READ, |
+ NULL, |
+ &error_code); |
+ if (error_code != base::PLATFORM_FILE_OK) { |
+ LOG(ERROR) << "Failed to open NaCl IRT file \"" |
+ << irt_filepath.LossyDisplayName() |
+ << "\": " << error_code; |
} |
} |
-void NaClProcessHost::OpenIrtFileDone(base::PlatformFileError error_code, |
- base::PassPlatformFile file, |
- bool created) { |
+void NaClProcessHost::OnProcessLaunched() { |
+ SendStart(irt_platform_file_); |
+} |
+ |
+static bool SendHandleToSelLdr( |
+ base::ProcessHandle processh, |
+ nacl::Handle sourceh, bool close_source, |
+ std::vector<nacl::FileDescriptor> *handles_for_sel_ldr) { |
+#if defined(OS_WIN) |
+ HANDLE channel; |
+ int flags = DUPLICATE_SAME_ACCESS; |
+ if (close_source) |
+ flags |= DUPLICATE_CLOSE_SOURCE; |
+ if (!DuplicateHandle(GetCurrentProcess(), |
+ reinterpret_cast<HANDLE>(sourceh), |
+ processh, |
+ &channel, |
+ 0, // Unused given DUPLICATE_SAME_ACCESS. |
+ FALSE, |
+ flags)) { |
+ LOG(ERROR) << "DuplicateHandle() failed"; |
+ return false; |
+ } |
+ handles_for_sel_ldr->push_back( |
+ reinterpret_cast<nacl::FileDescriptor>(channel)); |
+#else |
+ nacl::FileDescriptor channel; |
+ channel.fd = sourceh; |
+ channel.auto_close = close_source; |
+ handles_for_sel_ldr->push_back(channel); |
+#endif |
+ return true; |
+} |
+ |
+void NaClProcessHost::SendStart(base::PlatformFile irt_file) { |
std::vector<nacl::FileDescriptor> handles_for_renderer; |
base::ProcessHandle nacl_process_handle; |
- bool have_irt_file = false; |
- if (base::PLATFORM_FILE_OK == error_code) { |
- internal_->sockets_for_sel_ldr.push_back(file.ReleaseValue()); |
- have_irt_file = true; |
- } else { |
- LOG(ERROR) << "Failed to open the NaCl IRT library file"; |
- } |
for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { |
#if defined(OS_WIN) |
@@ -345,28 +381,18 @@ void NaClProcessHost::OpenIrtFileDone(base::PlatformFileError error_code, |
std::vector<nacl::FileDescriptor> handles_for_sel_ldr; |
for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { |
-#if defined(OS_WIN) |
- HANDLE channel; |
- if (!DuplicateHandle(GetCurrentProcess(), |
- reinterpret_cast<HANDLE>( |
- internal_->sockets_for_sel_ldr[i]), |
- handle(), |
- &channel, |
- 0, // Unused given DUPLICATE_SAME_ACCESS. |
- FALSE, |
- DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
- LOG(ERROR) << "DuplicateHandle() failed"; |
+ if (!SendHandleToSelLdr(handle(), |
+ internal_->sockets_for_sel_ldr[i], true, |
+ &handles_for_sel_ldr)) { |
delete this; |
return; |
} |
- handles_for_sel_ldr.push_back( |
- reinterpret_cast<nacl::FileDescriptor>(channel)); |
-#else |
- nacl::FileDescriptor channel; |
- channel.fd = internal_->sockets_for_sel_ldr[i]; |
- channel.auto_close = true; |
- handles_for_sel_ldr.push_back(channel); |
-#endif |
+ } |
+ |
+ // Send over the IRT file handle. We don't close our own copy! |
+ if (!SendHandleToSelLdr(handle(), irt_file, false, &handles_for_sel_ldr)) { |
+ delete this; |
+ return; |
} |
#if defined(OS_MACOSX) |
@@ -391,7 +417,7 @@ void NaClProcessHost::OpenIrtFileDone(base::PlatformFileError error_code, |
handles_for_sel_ldr.push_back(memory_fd); |
#endif |
- Send(new NaClProcessMsg_Start(handles_for_sel_ldr, have_irt_file)); |
+ Send(new NaClProcessMsg_Start(handles_for_sel_ldr)); |
internal_->sockets_for_sel_ldr.clear(); |
} |