snapuserd: Handle real time signal 36

Add a signal handler for real time signal 36 which
is primarily used by profilers. Default action is to
terminate the daemon if there is no signal handler. We
don't want daemon to get terminated, hence just capture
the signal and ignore it.

Bug: 201497662
Test: cow_snapuserd_test, pkill -36 snapuserd
Signed-off-by: Akilesh Kailash <akailash@google.com>
Change-Id: Ife5a8bdb7344956076bc4223c19a126b90a00706
diff --git a/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp
index bff0a50..44ea2cb 100644
--- a/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/cow_snapuserd_test.cpp
@@ -109,6 +109,7 @@
     void MergeInterruptRandomly(int max_duration);
     void ReadDmUserBlockWithoutDaemon();
     void ReadLastBlock();
+    void TestRealTimeSignal();
 
     std::string snapshot_dev() const { return snapshot_dev_->path(); }
 
@@ -152,6 +153,7 @@
     size_t size_ = 50_MiB;
     int cow_num_sectors_;
     int total_base_size_;
+    pid_t pid_;
 };
 
 class CowSnapuserdMetadataTest final {
@@ -254,6 +256,7 @@
     } else {
         client_ = SnapuserdClient::Connect(kSnapuserdSocketTest, 10s);
         ASSERT_NE(client_, nullptr);
+        pid_ = pid;
     }
 }
 
@@ -769,6 +772,16 @@
     ASSERT_FALSE(snapshot_dev_->path().empty());
 }
 
+void CowSnapuserdTest::TestRealTimeSignal() {
+    StartSnapuserdDaemon();
+    ASSERT_EQ(kill(pid_, 36), 0);  // Real time signal 36
+    ASSERT_EQ(kill(pid_, 0), 0);   // Verify pid exists
+    ASSERT_TRUE(client_->DetachSnapuserd());
+    std::this_thread::sleep_for(1s);
+    client_->CloseConnection();
+    client_ = nullptr;
+}
+
 void CowSnapuserdTest::SetupImpl() {
     CreateBaseDevice();
     CreateCowDevice();
@@ -1278,6 +1291,11 @@
     harness.Shutdown();
 }
 
+TEST(Snapuserd_Test, Snapshot_TestRealTimeSignal) {
+    CowSnapuserdTest harness;
+    harness.TestRealTimeSignal();
+}
+
 }  // namespace snapshot
 }  // namespace android
 
diff --git a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
index e05822e..e2ed7ed 100644
--- a/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
+++ b/fs_mgr/libsnapshot/snapuserd/snapuserd_daemon.cpp
@@ -29,6 +29,8 @@
 DEFINE_bool(socket_handoff, false,
             "If true, perform a socket hand-off with an existing snapuserd instance, then exit.");
 
+constexpr int kProfilingSignal = __SIGRTMIN + 4;
+
 namespace android {
 namespace snapshot {
 
@@ -39,6 +41,7 @@
     sigdelset(&signal_mask_, SIGINT);
     sigdelset(&signal_mask_, SIGTERM);
     sigdelset(&signal_mask_, SIGUSR1);
+    sigdelset(&signal_mask_, kProfilingSignal);
 
     // Masking signals here ensure that after this point, we won't handle INT/TERM
     // until after we call into ppoll()
@@ -46,6 +49,7 @@
     signal(SIGTERM, Daemon::SignalHandler);
     signal(SIGPIPE, Daemon::SignalHandler);
     signal(SIGUSR1, Daemon::SignalHandler);
+    signal(kProfilingSignal, Daemon::SignalHandler);
 
     MaskAllSignalsExceptIntAndTerm();
 
@@ -83,6 +87,7 @@
     sigdelset(&signal_mask, SIGTERM);
     sigdelset(&signal_mask, SIGPIPE);
     sigdelset(&signal_mask, SIGUSR1);
+    sigdelset(&signal_mask, kProfilingSignal);
     if (sigprocmask(SIG_SETMASK, &signal_mask, NULL) != 0) {
         PLOG(ERROR) << "Failed to set sigprocmask";
     }
@@ -116,6 +121,10 @@
             LOG(ERROR) << "Received SIGPIPE signal";
             break;
         }
+        case kProfilingSignal: {
+            LOG(INFO) << "Received real-time signal SIGRTMIN+4";
+            break;
+        }
         case SIGUSR1: {
             LOG(INFO) << "Received SIGUSR1, attaching to proxy socket";
             Daemon::Instance().ReceivedSocketSignal();