| Index: base/process_util_posix.cc
|
| ===================================================================
|
| --- base/process_util_posix.cc (revision 30209)
|
| +++ base/process_util_posix.cc (working copy)
|
| @@ -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 @@
|
|
|
| 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 @@
|
| // 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 @@
|
| 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;
|
|
|