diff options
author | bsy@google.com <bsy@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 08:11:37 +0000 |
---|---|---|
committer | bsy@google.com <bsy@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-06-20 08:11:37 +0000 |
commit | ccf4747ae4366a25f45452524acafae2e6b16739 (patch) | |
tree | 8a622bc3b77223e5c1980fb7945ad7d6ba58249b | |
parent | b360d67852164cca4d5d30758c5d6eb87786ee95 (diff) | |
download | chromium_src-ccf4747ae4366a25f45452524acafae2e6b16739.zip chromium_src-ccf4747ae4366a25f45452524acafae2e6b16739.tar.gz chromium_src-ccf4747ae4366a25f45452524acafae2e6b16739.tar.bz2 |
Init NaClChromeMainArgs number_of_cores member so apps can size threadpools
The outer sandbox on Linux and OSX was preventing
sysconf(_SC_NPROCESSORS_ONLN) from succeeding, so that NaCl
applications that need the number of processors/cores to, e.g., figure
out the appropriate size for threadpools were getting a bogus value
(-1 when using newlib and 1 when using glibc).
This is a reland of r204389
(https://chromiumcodereview.appspot.com/16047003) which was reverted
because of test failures on Win7 and Aura build bots -- even though
the test passed on a desktop Win7 machine. Consultation with bradn and
ncbray still indicate bot issues, but who knows?
TEST= browser_tests --gtest_filter=*Sysconf*
BUG= 176522
Review URL: https://chromiumcodereview.appspot.com/16761002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207350 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/nacl/nacl_helper_linux.cc | 12 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.cc | 8 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.h | 13 | ||||
-rw-r--r-- | chrome/nacl/nacl_main.cc | 9 | ||||
-rw-r--r-- | chrome/test/data/nacl/nacl_test_data.gyp | 17 | ||||
-rw-r--r-- | chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc | 116 | ||||
-rw-r--r-- | chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.html | 57 | ||||
-rw-r--r-- | chrome/test/nacl/nacl_browsertest.cc | 66 |
8 files changed, 294 insertions, 4 deletions
diff --git a/chrome/nacl/nacl_helper_linux.cc b/chrome/nacl/nacl_helper_linux.cc index 0faed7f1..7134457 100644 --- a/chrome/nacl/nacl_helper_linux.cc +++ b/chrome/nacl/nacl_helper_linux.cc @@ -40,7 +40,8 @@ namespace { // side of the fork. See zygote_main_linux.cc:HandleForkRequest from // if (!child) { void BecomeNaClLoader(const std::vector<int>& child_fds, - size_t prereserved_sandbox_size) { + size_t prereserved_sandbox_size, + int number_of_cores) { VLOG(1) << "NaCl loader: setting up IPC descriptor"; // don't need zygote FD any more if (HANDLE_EINTR(close(kNaClZygoteDescriptor)) != 0) @@ -56,6 +57,7 @@ void BecomeNaClLoader(const std::vector<int>& child_fds, base::MessageLoopForIO main_message_loop; NaClListener listener; listener.set_prereserved_sandbox_size(prereserved_sandbox_size); + listener.set_number_of_cores(number_of_cores); listener.Listen(); _exit(0); } @@ -63,7 +65,8 @@ void BecomeNaClLoader(const std::vector<int>& child_fds, // Some of this code was lifted from // content/browser/zygote_main_linux.cc:ForkWithRealPid() void HandleForkRequest(const std::vector<int>& child_fds, - size_t prereserved_sandbox_size) { + size_t prereserved_sandbox_size, + int number_of_cores) { VLOG(1) << "nacl_helper: forking"; pid_t childpid = fork(); if (childpid < 0) { @@ -101,7 +104,7 @@ void HandleForkRequest(const std::vector<int>& child_fds, if (HANDLE_EINTR(close(child_fds[kNaClParentFDIndex])) != 0) LOG(ERROR) << "close(child_fds[kNaClParentFDIndex]) failed"; if (validack) { - BecomeNaClLoader(child_fds, prereserved_sandbox_size); + BecomeNaClLoader(child_fds, prereserved_sandbox_size, number_of_cores); } else { LOG(ERROR) << "Failed to synch with zygote"; } @@ -239,6 +242,7 @@ int main(int argc, char* argv[]) { #endif std::vector<int> empty; // for SendMsg() calls size_t prereserved_sandbox_size = CheckReservedAtZero(); + int number_of_cores = sysconf(_SC_NPROCESSORS_ONLN); CheckRDebug(argv[0]); @@ -275,7 +279,7 @@ int main(int argc, char* argv[]) { } else if (msglen == sizeof(kNaClForkRequest) - 1 && memcmp(buf, kNaClForkRequest, msglen) == 0) { if (kNaClParentFDIndex + 1 == fds.size()) { - HandleForkRequest(fds, prereserved_sandbox_size); + HandleForkRequest(fds, prereserved_sandbox_size, number_of_cores); continue; // fork succeeded. Note: child does not return } else { LOG(ERROR) << "nacl_helper: unexpected number of fds, got " diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index 8d91a8b..568a107 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -7,6 +7,10 @@ #include <errno.h> #include <stdlib.h> +#if defined(OS_POSIX) +#include <unistd.h> +#endif + #include "base/command_line.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" @@ -174,6 +178,9 @@ NaClListener::NaClListener() : shutdown_event_(true, false), #if defined(OS_LINUX) prereserved_sandbox_size_(0), #endif +#if defined(OS_POSIX) + number_of_cores_(-1), // unknown/error +#endif main_loop_(NULL) { io_thread_.StartWithOptions( base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); @@ -260,6 +267,7 @@ void NaClListener::OnStart(const nacl::NaClStartParams& params) { LOG(ERROR) << "Failed to dup() the urandom FD"; return; } + args->number_of_cores = number_of_cores_; args->create_memory_object_func = CreateMemoryObject; # if defined(OS_MACOSX) CHECK(handles.size() >= 1); diff --git a/chrome/nacl/nacl_listener.h b/chrome/nacl/nacl_listener.h index 2936eee..a6cec25 100644 --- a/chrome/nacl/nacl_listener.h +++ b/chrome/nacl/nacl_listener.h @@ -34,6 +34,11 @@ class NaClListener : public IPC::Listener { prereserved_sandbox_size_ = prereserved_sandbox_size; } #endif +#if defined(OS_POSIX) + void set_number_of_cores(int number_of_cores) { + number_of_cores_ = number_of_cores; + } +#endif private: void OnStart(const nacl::NaClStartParams& params); @@ -51,6 +56,14 @@ class NaClListener : public IPC::Listener { #if defined(OS_LINUX) size_t prereserved_sandbox_size_; #endif +#if defined(OS_POSIX) + // The outer sandbox on Linux and OSX prevents + // sysconf(_SC_NPROCESSORS) from working; in Windows, there are no + // problems with invoking GetSystemInfo. Therefore, only in + // OS_POSIX do we need to supply the number of cores into the + // NaClChromeMainArgs object. + int number_of_cores_; +#endif // Used to identify what thread we're on. base::MessageLoop* main_loop_; diff --git a/chrome/nacl/nacl_main.cc b/chrome/nacl/nacl_main.cc index fa4835e..112a9c4 100644 --- a/chrome/nacl/nacl_main.cc +++ b/chrome/nacl/nacl_main.cc @@ -33,6 +33,12 @@ int NaClMain(const content::MainFunctionParams& parameters) { bool no_sandbox = parsed_command_line.HasSwitch(switches::kNoSandbox); platform.InitSandboxTests(no_sandbox); +#if defined(OS_POSIX) + // The number of cores must be obtained before the invocation of + // platform.EnableSandbox(), so cannot simply be inlined below. + int number_of_cores = sysconf(_SC_NPROCESSORS_ONLN); +#endif + if (!no_sandbox) { platform.EnableSandbox(); } @@ -40,6 +46,9 @@ int NaClMain(const content::MainFunctionParams& parameters) { if (sandbox_test_result) { NaClListener listener; +#if defined(OS_POSIX) + listener.set_number_of_cores(number_of_cores); +#endif listener.Listen(); } else { // This indirectly prevents the test-harness-success-cookie from being set, diff --git a/chrome/test/data/nacl/nacl_test_data.gyp b/chrome/test/data/nacl/nacl_test_data.gyp index 79598b0..f952d40 100644 --- a/chrome/test/data/nacl/nacl_test_data.gyp +++ b/chrome/test/data/nacl/nacl_test_data.gyp @@ -59,6 +59,23 @@ }, }, { + 'target_name': 'sysconf_nprocessors_onln_test', + 'type': 'none', + 'variables': { + 'nexe_target': 'sysconf_nprocessors_onln_test', + 'build_newlib': 1, + 'build_glibc': 1, + 'build_pnacl_newlib': 1, + 'nexe_destination_dir': 'nacl_test_data', + 'sources': [ + 'sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc', + ], + 'test_files': [ + 'sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.html', + ], + }, + }, + { 'target_name': 'ppapi_test_lib', 'type': 'none', 'variables': { diff --git a/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc b/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc new file mode 100644 index 0000000..4c12d83 --- /dev/null +++ b/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.cc @@ -0,0 +1,116 @@ +/* + * Copyright 2013 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/* + * Post-message based test for simple rpc based access to sysconf result. + */ + +#include <assert.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/fcntl.h> +#include <unistd.h> + +#include "ppapi/cpp/instance.h" +#include "ppapi/cpp/module.h" +#include "ppapi/cpp/var.h" + +#define TELEMETRY 1 + +void NumProcessors(const pp::Var& message_data, std::string* out) { + int num_cores; + char string_rep[16]; + + num_cores = sysconf(_SC_NPROCESSORS_ONLN); +#if TELEMETRY + fprintf(stderr, "NaCl process: sysconf(_SC_NPROCESSORS_ONLN) = %d\n", + num_cores); +#endif + snprintf(string_rep, sizeof string_rep, "%d", num_cores); + *out = string_rep; +} + +struct PostMessageHandlerDesc { + char const *request; + void (*handler)(const pp::Var& message_data, std::string* out); +}; + +// This object represents one time the page says <embed>. +class MyInstance : public pp::Instance { + public: + explicit MyInstance(PP_Instance instance) : pp::Instance(instance) {} + virtual ~MyInstance() {} + virtual void HandleMessage(const pp::Var& message_data); +}; + +// HandleMessage gets invoked when postMessage is called on the DOM +// element associated with this plugin instance. In this case, if we +// are given a string, we'll post a message back to JavaScript with a +// reply string -- essentially treating this as a string-based RPC. +void MyInstance::HandleMessage(const pp::Var& message_data) { + static struct PostMessageHandlerDesc kMsgHandlers[] = { + { "nprocessors", NumProcessors }, + { reinterpret_cast<char const *>(NULL), + reinterpret_cast<void (*)(const pp::Var&, std::string*)>(NULL) } + }; + +#if TELEMETRY + fprintf(stderr, "Entered HandleMessage\n"); + fflush(NULL); +#endif + + if (message_data.is_string()) { + std::string op_name(message_data.AsString()); + size_t len; + + fprintf(stderr, "Searching for handler for request \"%s\".\n", + op_name.c_str()); + + std::string sb; + + for (size_t ix = 0; kMsgHandlers[ix].request != NULL; ++ix) { + if (op_name == kMsgHandlers[ix].request) { + fprintf(stderr, "found at index %u\n", ix); + kMsgHandlers[ix].handler(message_data, &sb); + break; + } + } + + len = strlen(sb.c_str()); + fprintf(stderr, "posting reply len %d\n", len); + fprintf(stderr, "posting reply \"%s\".\n", sb.c_str()); + + PostMessage(pp::Var(sb)); +#if TELEMETRY + fprintf(stderr, "Leaving HandleMessage\n"); + fflush(NULL); +#endif + } +} + +// This object is the global object representing this plugin library as long +// as it is loaded. +class MyModule : public pp::Module { + public: + MyModule() : pp::Module() {} + virtual ~MyModule() {} + + // Override CreateInstance to create your customized Instance object. + virtual pp::Instance* CreateInstance(PP_Instance instance) { + return new MyInstance(instance); + } +}; + +namespace pp { + +// Factory function for your specialization of the Module object. +Module* CreateModule() { + return new MyModule(); +} + +} // namespace pp diff --git a/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.html b/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.html new file mode 100644 index 0000000..cdc45e4 --- /dev/null +++ b/chrome/test/data/nacl/sysconf_nprocessors_onln/sysconf_nprocessors_onln_test.html @@ -0,0 +1,57 @@ +<!-- + Copyright 2013 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can + be found in the LICENSE file. +--> +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html> + <head> + <meta http-equiv="Pragma" content="no-cache" /> + <meta http-equiv="Expires" content="-1" /> + <script type="text/javascript" src="nacltest.js"></script> + <title>Native Client _SC_NPROCESSORS_ONLN Test</title> + </head> + + <body id="body"> + <h1>Native Client _SC_NPROCESSORS_ONLN Test</h1> + <script type="text/javascript"> + //<![CDATA[ +var tester = new Tester($('body')); +var args = getTestArguments({'cpu_count' : + 'THIS TEST CANNOT RUN STANDALONE -- run using browser_test instead'}); + +function setupModule(manifest_url) { + var embed = document.createElement("embed"); + embed.src = manifest_url; + embed.type = "application/x-nacl"; + if (getTestArguments()["pnacl"] !== undefined) { + embed.type = "application/x-pnacl"; + } + document.body.appendChild(embed); + return embed; +} + +function setupTests(tester, plugin) { + tester.addAsyncTest("TestSysconfNprocessors", function(status) { + plugin.addEventListener("message", function handler(message_event) { + this.removeEventListener("message", handler, false); + status.assertEqual(message_event.data, args.cpu_count); + status.pass(); + }, false); + plugin.postMessage("nprocessors"); + }); +} + +function runTests() { + var module = setupModule("sysconf_nprocessors_onln_test.nmf"); + setupTests(tester, module); + tester.waitFor(module); + tester.run(); +} + +runTests(); + //]]> + </script> + </body> +</html> diff --git a/chrome/test/nacl/nacl_browsertest.cc b/chrome/test/nacl/nacl_browsertest.cc index dffa442..5d9689c 100644 --- a/chrome/test/nacl/nacl_browsertest.cc +++ b/chrome/test/nacl/nacl_browsertest.cc @@ -2,6 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <stdio.h> +#if defined(OS_POSIX) +#include <unistd.h> +#elif defined(OS_WIN) +#include <windows.h> +#endif + +#define TELEMETRY 1 + #include "chrome/test/nacl/nacl_browsertest_util.h" namespace { @@ -19,6 +28,7 @@ namespace { #define MAYBE_CrossOriginFail DISABLED_CrossOriginFail #define MAYBE_SameOriginCookie DISABLED_SameOriginCookie #define MAYBE_CORSNoCookie DISABLED_CORSNoCookie +#define MAYBE_SysconfNprocessorsOnln DISABLED_SysconfNprocessorsOnln #else #define MAYBE_SimpleLoad SimpleLoad #define MAYBE_ExitStatus0 ExitStatus0 @@ -31,6 +41,7 @@ namespace { #define MAYBE_CrossOriginFail CrossOriginFail #define MAYBE_SameOriginCookie SameOriginCookie #define MAYBE_CORSNoCookie CORSNoCookie +#define MAYBE_SysconfNprocessorsOnln SysconfNprocessorsOnln #endif NACL_BROWSER_TEST_F(NaClBrowserTest, MAYBE_SimpleLoad, { @@ -64,6 +75,61 @@ NACL_BROWSER_TEST_F(NaClBrowserTest, MAYBE_PnaclMimeType, { RunLoadTest(FILE_PATH_LITERAL("pnacl_mime_type.html")); }) +// Some versions of Visual Studio does not like preprocessor +// conditionals inside the argument of a macro, so we put the +// conditionals on a helper function. We are already in an anonymous +// namespace, so the name of the helper is not visible in external +// scope. +#if defined(OS_POSIX) +base::FilePath::StringType NumberOfCoresAsFilePathString() { + char string_rep[23]; + long nprocessors = sysconf(_SC_NPROCESSORS_ONLN); +#if TELEMETRY + fprintf(stderr, "browser says nprocessors = %ld\n", nprocessors); + fflush(NULL); +#endif + snprintf(string_rep, sizeof string_rep, "%ld", nprocessors); + return string_rep; +} +#elif defined(OS_WIN) +base::FilePath::StringType NumberOfCoresAsFilePathString() { + wchar_t string_rep[23]; + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); +#if TELEMETRY + fprintf(stderr, "browser says nprocessors = %d\n", + system_info.dwNumberOfProcessors); + fflush(NULL); +#endif + _snwprintf_s(string_rep, sizeof string_rep, _TRUNCATE, L"%u", + system_info.dwNumberOfProcessors); + return string_rep; +} +#endif + +#if TELEMETRY +static void PathTelemetry(base::FilePath::StringType const &path) { +# if defined(OS_WIN) + fwprintf(stderr, L"path = %s\n", path.c_str()); +# else + fprintf(stderr, "path = %s\n", path.c_str()); +# endif + fflush(NULL); +} +#else +static void PathTelemetry(base::FilePath::StringType const &path) { + (void) path; +} +#endif + +NACL_BROWSER_TEST_F(NaClBrowserTest, MAYBE_SysconfNprocessorsOnln, { + base::FilePath::StringType path = + FILE_PATH_LITERAL("sysconf_nprocessors_onln_test.html?cpu_count="); + path = path + NumberOfCoresAsFilePathString(); + PathTelemetry(path); + RunNaClIntegrationTest(path); +}) + IN_PROC_BROWSER_TEST_F(NaClBrowserTestStatic, MAYBE_CrossOriginCORS) { RunLoadTest(FILE_PATH_LITERAL("cross_origin/cors.html")); } |