diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-13 17:38:49 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-13 17:38:49 +0000 |
commit | c78566309f95a11cd5253e1cac681038d9885f21 (patch) | |
tree | 74bac802565ea385f1585d5d7d8ca15891b1979c | |
parent | 2ccbdbe2508fdf17fde95a96ee197d45faabe467 (diff) | |
download | chromium_src-c78566309f95a11cd5253e1cac681038d9885f21.zip chromium_src-c78566309f95a11cd5253e1cac681038d9885f21.tar.gz chromium_src-c78566309f95a11cd5253e1cac681038d9885f21.tar.bz2 |
Port crash_cache tool to Linux.
Review URL: http://codereview.chromium.org/17353
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7939 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/process_util.h | 6 | ||||
-rw-r--r-- | base/process_util_posix.cc | 20 | ||||
-rw-r--r-- | base/process_util_win.cc | 14 | ||||
-rw-r--r-- | net/crash_cache.scons | 4 | ||||
-rw-r--r-- | net/disk_cache/rankings.cc | 49 | ||||
-rw-r--r-- | net/disk_cache/stress_cache.cc | 36 | ||||
-rw-r--r-- | net/tools/crash_cache/crash_cache.cc | 46 |
7 files changed, 101 insertions, 74 deletions
diff --git a/base/process_util.h b/base/process_util.h index c88d341..7eabdbe 100644 --- a/base/process_util.h +++ b/base/process_util.h @@ -147,6 +147,12 @@ bool KillProcess(int process_id, int exit_code, bool wait); // process hasn't terminated yet. bool DidProcessCrash(ProcessHandle handle); +// Waits for process to exit. In POSIX systems, if the process hasn't been +// signaled then puts the exit code in |exit_code|; otherwise it's considered +// a failure. On Windows |exit_code| is always filled. Returns true on success, +// and closes |handle| in any case. +bool WaitForExitCode(ProcessHandle handle, int* exit_code); + // Wait for all the processes based on the named executable to exit. If filter // is non-null, then only processes selected by the filter are waited on. // Returns after all processes have exited or wait_milliseconds have expired. diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc index dee917d..8e6781e 100644 --- a/base/process_util_posix.cc +++ b/base/process_util_posix.cc @@ -4,6 +4,7 @@ #include "base/process_util.h" +#include <errno.h> #include <signal.h> #include <sys/resource.h> #include <sys/time.h> @@ -96,6 +97,25 @@ void RaiseProcessToHighPriority() { // setpriority() or sched_getscheduler, but these all require extra rights. } +bool WaitForExitCode(ProcessHandle handle, int* exit_code) { + int status; + while (waitpid(handle, &status, 0) == -1) { + if (errno != EINTR) { + NOTREACHED(); + return false; + } + } + + if (WIFEXITED(status)) { + *exit_code = WEXITSTATUS(status); + return true; + } + + // If it didn't exit cleanly, it must have been signaled. + DCHECK(WIFSIGNALED(status)); + return false; +} + bool WaitForSingleProcess(ProcessHandle handle, int wait_milliseconds) { // This POSIX version of this function only guarantees that we wait no less // than |wait_milliseconds| for the proces to exit. The child process may diff --git a/base/process_util_win.cc b/base/process_util_win.cc index 1203629..a69f5d5 100644 --- a/base/process_util_win.cc +++ b/base/process_util_win.cc @@ -10,6 +10,7 @@ #include "base/histogram.h" #include "base/logging.h" +#include "base/scoped_handle_win.h" #include "base/scoped_ptr.h" namespace { @@ -226,6 +227,19 @@ bool DidProcessCrash(ProcessHandle handle) { return true; } +bool WaitForExitCode(ProcessHandle handle, int* exit_code) { + ScopedHandle closer(handle); // Ensure that we always close the handle. + if (::WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) { + NOTREACHED(); + return false; + } + DWORD temp_code; // Don't clobber out-parameters in case of failure. + if (!::GetExitCodeProcess(handle, &temp_code)) + return false; + *exit_code = temp_code; + return true; +} + NamedProcessIterator::NamedProcessIterator(const std::wstring& executable_name, const ProcessFilter* filter) : started_iteration_(false), diff --git a/net/crash_cache.scons b/net/crash_cache.scons index 9bb5124..4480008b 100644 --- a/net/crash_cache.scons +++ b/net/crash_cache.scons @@ -31,8 +31,8 @@ input_files = ChromeFileList([ ]) -if not env.AnyBits('linux', 'mac'): - # TODO(port): port to linux and mac? +if not env.Bit('mac'): + # TODO(port): port to mac? env.ChromeTestProgram('crash_cache', input_files) p = env.ChromeMSVSProject('$NET_DIR/build/crash_cache.vcproj', diff --git a/net/disk_cache/rankings.cc b/net/disk_cache/rankings.cc index e3ff489..d786077 100644 --- a/net/disk_cache/rankings.cc +++ b/net/disk_cache/rankings.cc @@ -63,10 +63,20 @@ enum CrashLocation { ON_REMOVE_3, ON_REMOVE_4, ON_REMOVE_5, ON_REMOVE_6, ON_REMOVE_7, ON_REMOVE_8 }; +void TerminateSelf() { +#if defined(OS_WIN) + // Windows does more work on _exit() than we would like, so we force exit. + TerminateProcess(GetCurrentProcess(), 0); +#elif defined(OS_POSIX) + // On POSIX, _exit() will terminate the process with minimal cleanup, + // and it is cleaner than killing. + _exit(0); +#endif +} + // Generates a crash on debug builds, acording to the value of g_rankings_crash. // This used by crash_cache.exe to generate unit-test files. void GenerateCrash(CrashLocation location) { -#if defined(OS_WIN) #ifndef NDEBUG if (disk_cache::NO_CRASH == g_rankings_crash) return; @@ -75,26 +85,32 @@ void GenerateCrash(CrashLocation location) { switch (g_rankings_crash) { case disk_cache::INSERT_ONE_1: case disk_cache::INSERT_LOAD_1: - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); + default: + break; } break; case ON_INSERT_2: if (disk_cache::INSERT_EMPTY_1 == g_rankings_crash) - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); break; case ON_INSERT_3: switch (g_rankings_crash) { case disk_cache::INSERT_EMPTY_2: case disk_cache::INSERT_ONE_2: case disk_cache::INSERT_LOAD_2: - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); + default: + break; } break; case ON_INSERT_4: switch (g_rankings_crash) { case disk_cache::INSERT_EMPTY_3: case disk_cache::INSERT_ONE_3: - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); + default: + break; } break; case ON_REMOVE_1: @@ -103,42 +119,48 @@ void GenerateCrash(CrashLocation location) { case disk_cache::REMOVE_HEAD_1: case disk_cache::REMOVE_TAIL_1: case disk_cache::REMOVE_LOAD_1: - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); + default: + break; } break; case ON_REMOVE_2: if (disk_cache::REMOVE_ONE_2 == g_rankings_crash) - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); break; case ON_REMOVE_3: if (disk_cache::REMOVE_ONE_3 == g_rankings_crash) - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); break; case ON_REMOVE_4: if (disk_cache::REMOVE_HEAD_2 == g_rankings_crash) - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); break; case ON_REMOVE_5: if (disk_cache::REMOVE_TAIL_2 == g_rankings_crash) - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); break; case ON_REMOVE_6: if (disk_cache::REMOVE_TAIL_3 == g_rankings_crash) - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); break; case ON_REMOVE_7: switch (g_rankings_crash) { case disk_cache::REMOVE_ONE_4: case disk_cache::REMOVE_LOAD_2: case disk_cache::REMOVE_HEAD_3: - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); + default: + break; } break; case ON_REMOVE_8: switch (g_rankings_crash) { case disk_cache::REMOVE_HEAD_4: case disk_cache::REMOVE_LOAD_3: - TerminateProcess(GetCurrentProcess(), 0); + TerminateSelf(); + default: + break; } break; default: @@ -146,7 +168,6 @@ void GenerateCrash(CrashLocation location) { return; } #endif // NDEBUG -#endif // OS_WIN } } // namespace diff --git a/net/disk_cache/stress_cache.cc b/net/disk_cache/stress_cache.cc index 610cdc3..03fb4c1 100644 --- a/net/disk_cache/stress_cache.cc +++ b/net/disk_cache/stress_cache.cc @@ -10,16 +10,6 @@ // The child application has two threads: one to exercise the cache in an // infinite loop, and another one to asynchronously kill the process. -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_POSIX) -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#endif - #include <string> #include <vector> @@ -61,32 +51,12 @@ int RunSlave(int iteration) { return kError; } - // TODO: Find a good place for this kind of code in process_util. -#if defined(OS_WIN) - WaitForSingleObject(handle, INFINITE); - int code; - bool ok = GetExitCodeProcess(handle, - reinterpret_cast<LPDWORD>(&code)) ? true : - false; - CloseHandle(handle); - if (!ok) { + int exit_code; + if (!base::WaitForExitCode(handle, &exit_code)) { printf("Unable to get return code\n"); return kError; } - return code; -#elif defined(OS_POSIX) - int status; - wait(&status); - - if (WIFSIGNALED(status)) - return kError; - - if (WIFEXITED(status)) - return WEXITSTATUS(status); - - NOTREACHED(); - return kError; -#endif + return exit_code; } // Main loop for the master process. diff --git a/net/tools/crash_cache/crash_cache.cc b/net/tools/crash_cache/crash_cache.cc index 243ed45..df641a2 100644 --- a/net/tools/crash_cache/crash_cache.cc +++ b/net/tools/crash_cache/crash_cache.cc @@ -7,14 +7,15 @@ // works properly on debug mode, because the crash functionality is not compiled // on release builds of the cache. -#include <windows.h> #include <string> #include "base/at_exit.h" +#include "base/command_line.h" #include "base/file_util.h" #include "base/logging.h" #include "base/message_loop.h" #include "base/path_service.h" +#include "base/process_util.h" #include "base/string_util.h" #include "net/disk_cache/backend_impl.h" @@ -39,39 +40,31 @@ int RunSlave(RankCrashes action) { std::wstring exe; PathService::Get(base::FILE_EXE, &exe); - std::wstring command = StringPrintf(L"%ls %d", exe.c_str(), action); - - STARTUPINFO startup_info = {0}; - startup_info.cb = sizeof(startup_info); - PROCESS_INFORMATION process_info; - - // I really don't care about this call modifying the string. - if (!::CreateProcess(exe.c_str(), const_cast<wchar_t*>(command.c_str()), NULL, - NULL, FALSE, 0, NULL, NULL, &startup_info, - &process_info)) { +#if defined(OS_WIN) + CommandLine cmdline(StringPrintf(L"%ls %d", exe.c_str(), action)); +#elif defined(OS_POSIX) + std::vector<std::string> cmd_argv; + cmd_argv.push_back(WideToUTF8(exe)); + cmd_argv.push_back(IntToString(action)); + CommandLine cmdline(cmd_argv); +#endif + + base::ProcessHandle handle; + if (!base::LaunchApp(cmdline, false, false, &handle)) { printf("Unable to run test %d\n", action); return GENERIC; } - DWORD reason = ::WaitForSingleObject(process_info.hProcess, INFINITE); - - int code; - bool ok = ::GetExitCodeProcess(process_info.hProcess, - reinterpret_cast<PDWORD>(&code)) ? true : - false; + int exit_code; - ::CloseHandle(process_info.hProcess); - ::CloseHandle(process_info.hThread); - - if (!ok) { + if (!base::WaitForExitCode(handle, &exit_code)) { printf("Unable to get return code, test %d\n", action); return GENERIC; } + if (ALL_GOOD != exit_code) + printf("Test %d failed, code %d\n", action, exit_code); - if (ALL_GOOD != code) - printf("Test %d failed, code %d\n", action, code); - - return code; + return exit_code; } // Main loop for the master process. @@ -124,6 +117,9 @@ bool CreateTargetFolder(const std::wstring& path, RankCrashes action, *full_path = path; file_util::AppendToPath(full_path, folders[action]); + if (file_util::PathExists(*full_path)) + return false; + return file_util::CreateDirectory(*full_path); } |