Added a signal handler for SIGPIPE.

We've seen some unexpected SIGPIPE signals in cryptohomed and we want to
be able to find out where they are coming from.  This handler will
abort and print the IP if on x64.

BUG=chromium:367278
TEST=manual, on link

Change-Id: I88a253c1117bee448e759678b16f5e69afe3c4e2
Reviewed-on: https://chromium-review.googlesource.com/201417
Reviewed-by: Darren Krahn <dkrahn@chromium.org>
Commit-Queue: Darren Krahn <dkrahn@chromium.org>
Tested-by: Darren Krahn <dkrahn@chromium.org>
diff --git a/cryptohomed.cc b/cryptohomed.cc
index f9c27f8..b87f1b6 100644
--- a/cryptohomed.cc
+++ b/cryptohomed.cc
@@ -6,6 +6,8 @@
 
 #include <stdio.h>
 #include <unistd.h>
+#include <signal.h>
+#include <sys/ucontext.h>
 
 #include <base/at_exit.h>
 #include <base/command_line.h>
@@ -26,6 +28,18 @@
 //           We will need a "CheckKey" interface as well to simplify
 //           offline authentication checks.
 
+namespace {
+
+void HandlePipeSignal(int signal, siginfo_t* info, void* context_ptr) {
+  uint64_t source = 0;
+#if defined(__x86_64__)
+  ucontext_t* context = reinterpret_cast<ucontext_t*>(context_ptr);
+  source = context->uc_mcontext.gregs[REG_RIP];
+#endif
+  LOG(FATAL) << "SIGPIPE received from 0x" << std::hex << source;
+}
+
+}
 
 namespace switches {
 // Keeps std* open for debugging
@@ -40,6 +54,15 @@
 
   chromeos::InitLog(chromeos::kLogToSyslog | chromeos::kLogToStderr);
 
+  // Add a handler to do something informative on SIGPIPE.
+  // TODO(dkrahn): Remove this code once crbug.com/367278 is fixed.
+  struct sigaction pipe_action;
+  memset(&pipe_action, 0, sizeof(struct sigaction));
+  pipe_action.sa_flags = SA_SIGINFO;
+  pipe_action.sa_sigaction = &HandlePipeSignal;
+  CHECK(!sigaction(SIGPIPE, &pipe_action, NULL))
+      << "Failed to register SIGPIPE handler.";
+
   // Allow the commands to be configurable.
   CommandLine *cl = CommandLine::ForCurrentProcess();
   int noclose = cl->HasSwitch(switches::kNoCloseOnDaemonize);