Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3640)

Unified Diff: base/process_util_posix.cc

Issue 339024: Move console stack dumping code to a function so it can be reused in test_she... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/process_util.h ('k') | base/process_util_win.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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;
« no previous file with comments | « base/process_util.h ('k') | base/process_util_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698