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();