ShellSubscriber: install SIGPIPE handler

Install a handler that ignores SIGPIPE. Before this, SIGPIPE was not
being handled, which caused a SIGKILL to be sent to statsd. Note that
even if SIGPIPE is handled, writes to closed pipes will return EPIPE.

Bug: 153595161
Test: procedure specified in b/153595161
    1. cat statsd config | adb shell cmd stats data-subscribe
    2. Terminate the shell command
    3. cat statsd config | adb shell cmd stats data-subscribe
Change-Id: Ib5e679ccd7cdf7182452466b316488439871db99
diff --git a/cmds/statsd/src/main.cpp b/cmds/statsd/src/main.cpp
index d79b6a2..e394533 100644
--- a/cmds/statsd/src/main.cpp
+++ b/cmds/statsd/src/main.cpp
@@ -38,20 +38,27 @@
 
 shared_ptr<StatsService> gStatsService = nullptr;
 
-void sigHandler(int sig) {
-    if (gStatsService != nullptr) {
-        gStatsService->Terminate();
+void signalHandler(int sig) {
+    if (sig == SIGPIPE) {
+        // ShellSubscriber uses SIGPIPE as a signal to detect the end of the
+        // client process. Don't prematurely exit(1) here. Instead, ignore the
+        // signal and allow the write call to return EPIPE.
+        ALOGI("statsd received SIGPIPE. Ignoring signal.");
+        return;
     }
+
+    if (gStatsService != nullptr) gStatsService->Terminate();
     ALOGW("statsd terminated on receiving signal %d.", sig);
     exit(1);
 }
 
-void registerSigHandler()
+void registerSignalHandlers()
 {
     struct sigaction sa;
     sigemptyset(&sa.sa_mask);
     sa.sa_flags = 0;
-    sa.sa_handler = sigHandler;
+    sa.sa_handler = signalHandler;
+    sigaction(SIGPIPE, &sa, nullptr);
     sigaction(SIGHUP, &sa, nullptr);
     sigaction(SIGINT, &sa, nullptr);
     sigaction(SIGQUIT, &sa, nullptr);
@@ -79,7 +86,7 @@
         return -1;
     }
 
-    registerSigHandler();
+    registerSignalHandlers();
 
     gStatsService->sayHiToStatsCompanion();