summaryrefslogtreecommitdiffstats
path: root/base/process_util_posix.cc
diff options
context:
space:
mode:
authormaruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-27 18:03:47 +0000
committermaruel@chromium.org <maruel@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-10-27 18:03:47 +0000
commitd6fc9fd286eb7a3a6cad937da3b99cf8f4acd5c2 (patch)
treeff8de9ff438626c6d26a9df0acb94fadfd640431 /base/process_util_posix.cc
parent30be1ce62471386dbdebf8d8f4f87e31a772661c (diff)
downloadchromium_src-d6fc9fd286eb7a3a6cad937da3b99cf8f4acd5c2.zip
chromium_src-d6fc9fd286eb7a3a6cad937da3b99cf8f4acd5c2.tar.gz
chromium_src-d6fc9fd286eb7a3a6cad937da3b99cf8f4acd5c2.tar.bz2
Move console stack dumping code to a function so it can be reused in test_shell_tests.
TEST=none BUG=13770 Review URL: http://codereview.chromium.org/339024 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@30220 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/process_util_posix.cc')
-rw-r--r--base/process_util_posix.cc144
1 files changed, 86 insertions, 58 deletions
diff --git a/base/process_util_posix.cc b/base/process_util_posix.cc
index d365d01..d5eb4ee 100644
--- a/base/process_util_posix.cc
+++ b/base/process_util_posix.cc
@@ -16,7 +16,7 @@
#include <limits>
#include <set>
-#include "base/basictypes.h"
+#include "base/debug_util.h"
#include "base/eintr_wrapper.h"
#include "base/logging.h"
#include "base/platform_thread.h"
@@ -30,6 +30,68 @@ const int kMicrosecondsPerSecond = 1000000;
namespace base {
+namespace {
+
+int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds,
+ bool* success) {
+ // 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
+ // exit sometime before the timeout has ended but we may still block for
+ // up to 0.25 seconds after the fact.
+ //
+ // waitpid() has no direct support on POSIX for specifying a timeout, you can
+ // either ask it to block indefinitely or return immediately (WNOHANG).
+ // When a child process terminates a SIGCHLD signal is sent to the parent.
+ // Catching this signal would involve installing a signal handler which may
+ // affect other parts of the application and would be difficult to debug.
+ //
+ // Our strategy is to call waitpid() once up front to check if the process
+ // has already exited, otherwise to loop for wait_milliseconds, sleeping for
+ // at most 0.25 secs each time using usleep() and then calling waitpid().
+ //
+ // usleep() is speced to exit if a signal is received for which a handler
+ // has been installed. This means that when a SIGCHLD is sent, it will exit
+ // depending on behavior external to this function.
+ //
+ // This function is used primarily for unit tests, if we want to use it in
+ // the application itself it would probably be best to examine other routes.
+ int status = -1;
+ pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
+ static const int64 kQuarterSecondInMicroseconds = kMicrosecondsPerSecond / 4;
+
+ // If the process hasn't exited yet, then sleep and try again.
+ Time wakeup_time = Time::Now() + TimeDelta::FromMilliseconds(
+ wait_milliseconds);
+ while (ret_pid == 0) {
+ Time now = Time::Now();
+ if (now > wakeup_time)
+ break;
+ // Guaranteed to be non-negative!
+ int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
+ // Don't sleep for more than 0.25 secs at a time.
+ if (sleep_time_usecs > kQuarterSecondInMicroseconds) {
+ sleep_time_usecs = kQuarterSecondInMicroseconds;
+ }
+
+ // usleep() will return 0 and set errno to EINTR on receipt of a signal
+ // such as SIGCHLD.
+ usleep(sleep_time_usecs);
+ ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
+ }
+
+ if (success)
+ *success = (ret_pid != -1);
+
+ return status;
+}
+
+void StackDumpSignalHandler(int signal) {
+ StackTrace().PrintBacktrace();
+ _exit(1);
+}
+
+} // namespace
+
ProcessId GetCurrentProcId() {
return getpid();
}
@@ -323,6 +385,29 @@ void EnableTerminationOnHeapCorruption() {
// On POSIX, there nothing to do AFAIK.
}
+bool EnableInProcessStackDumping() {
+ // When running in an application, our code typically expects SIGPIPE
+ // to be ignored. Therefore, when testing that same code, it should run
+ // with SIGPIPE ignored as well.
+ struct sigaction action;
+ action.sa_handler = SIG_IGN;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ bool success = (sigaction(SIGPIPE, &action, NULL) == 0);
+
+ // TODO(phajdan.jr): Catch other crashy signals, like SIGABRT.
+ success &= (signal(SIGSEGV, &StackDumpSignalHandler) != SIG_ERR);
+ success &= (signal(SIGILL, &StackDumpSignalHandler) != SIG_ERR);
+ success &= (signal(SIGBUS, &StackDumpSignalHandler) != SIG_ERR);
+ success &= (signal(SIGFPE, &StackDumpSignalHandler) != SIG_ERR);
+ return success;
+}
+
+void AttachToConsole() {
+ // On POSIX, there nothing to do AFAIK. Maybe create a new console if none
+ // exist?
+}
+
void RaiseProcessToHighPriority() {
// On POSIX, we don't actually do anything here. We could try to nice() or
// setpriority() or sched_getscheduler, but these all require extra rights.
@@ -381,63 +466,6 @@ bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
return false;
}
-namespace {
-
-int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds,
- bool* success) {
- // 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
- // exit sometime before the timeout has ended but we may still block for
- // up to 0.25 seconds after the fact.
- //
- // waitpid() has no direct support on POSIX for specifying a timeout, you can
- // either ask it to block indefinitely or return immediately (WNOHANG).
- // When a child process terminates a SIGCHLD signal is sent to the parent.
- // Catching this signal would involve installing a signal handler which may
- // affect other parts of the application and would be difficult to debug.
- //
- // Our strategy is to call waitpid() once up front to check if the process
- // has already exited, otherwise to loop for wait_milliseconds, sleeping for
- // at most 0.25 secs each time using usleep() and then calling waitpid().
- //
- // usleep() is speced to exit if a signal is received for which a handler
- // has been installed. This means that when a SIGCHLD is sent, it will exit
- // depending on behavior external to this function.
- //
- // This function is used primarily for unit tests, if we want to use it in
- // the application itself it would probably be best to examine other routes.
- int status = -1;
- pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
- static const int64 kQuarterSecondInMicroseconds = kMicrosecondsPerSecond/4;
-
- // If the process hasn't exited yet, then sleep and try again.
- Time wakeup_time = Time::Now() + TimeDelta::FromMilliseconds(
- wait_milliseconds);
- while (ret_pid == 0) {
- Time now = Time::Now();
- if (now > wakeup_time)
- break;
- // Guaranteed to be non-negative!
- int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
- // Don't sleep for more than 0.25 secs at a time.
- if (sleep_time_usecs > kQuarterSecondInMicroseconds) {
- sleep_time_usecs = kQuarterSecondInMicroseconds;
- }
-
- // usleep() will return 0 and set errno to EINTR on receipt of a signal
- // such as SIGCHLD.
- usleep(sleep_time_usecs);
- ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
- }
-
- if (success)
- *success = (ret_pid != -1);
-
- return status;
-}
-
-} // namespace
-
bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) {
bool waitpid_success;
int status;