summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-13 17:38:49 +0000
committerphajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-13 17:38:49 +0000
commitc78566309f95a11cd5253e1cac681038d9885f21 (patch)
tree74bac802565ea385f1585d5d7d8ca15891b1979c
parent2ccbdbe2508fdf17fde95a96ee197d45faabe467 (diff)
downloadchromium_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.h6
-rw-r--r--base/process_util_posix.cc20
-rw-r--r--base/process_util_win.cc14
-rw-r--r--net/crash_cache.scons4
-rw-r--r--net/disk_cache/rankings.cc49
-rw-r--r--net/disk_cache/stress_cache.cc36
-rw-r--r--net/tools/crash_cache/crash_cache.cc46
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);
}