From 11e55cb9c1e5efe553e36f1b5c04ab21883f66e1 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 10 Mar 2015 16:45:17 -0700 Subject: [PATCH 1/2] logd: add reinit command - respond to SIGHUP - respond to logd command "reinit" - respond to logd --reinit - reopens files on /data, eg: re-read of persistent properties Bug: 19681572 Change-Id: Iadac58e6653f027cb7355497bd675eef376ce0a8 --- logd/CommandListener.cpp | 16 +++++ logd/CommandListener.h | 11 ++++ logd/LogBuffer.cpp | 12 ++-- logd/LogBuffer.h | 1 + logd/main.cpp | 122 ++++++++++++++++++++++++++++++++++----- 5 files changed, 143 insertions(+), 19 deletions(-) diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp index d7088b4db..561ea3e50 100644 --- a/logd/CommandListener.cpp +++ b/logd/CommandListener.cpp @@ -44,6 +44,7 @@ CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/, registerCmd(new GetStatisticsCmd(buf)); registerCmd(new SetPruneListCmd(buf)); registerCmd(new GetPruneListCmd(buf)); + registerCmd(new ReinitCmd()); } CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader, @@ -296,6 +297,21 @@ int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli, return 0; } +CommandListener::ReinitCmd::ReinitCmd() + : LogCommand("reinit") +{ } + +int CommandListener::ReinitCmd::runCommand(SocketClient *cli, + int /*argc*/, char ** /*argv*/) { + setname(); + + reinit_signal_handler(SIGHUP); + + cli->sendMsg("success"); + + return 0; +} + int CommandListener::getLogSocket() { static const char socketName[] = "logd"; int sock = android_get_control_socket(socketName); diff --git a/logd/CommandListener.h b/logd/CommandListener.h index cd1c306ba..83e06b4b0 100644 --- a/logd/CommandListener.h +++ b/logd/CommandListener.h @@ -23,6 +23,9 @@ #include "LogReader.h" #include "LogListener.h" +// See main.cpp for implementation +void reinit_signal_handler(int /*signal*/); + class CommandListener : public FrameworkListener { LogBuffer &mBuf; @@ -60,6 +63,14 @@ private: LogBufferCmd(GetStatistics) LogBufferCmd(GetPruneList) LogBufferCmd(SetPruneList) + + class ReinitCmd : public LogCommand { + public: + ReinitCmd(); + virtual ~ReinitCmd() {} + int runCommand(SocketClient *c, int argc, char ** argv); + }; + }; #endif diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp index edda6c4e2..2b495abfd 100644 --- a/logd/LogBuffer.cpp +++ b/logd/LogBuffer.cpp @@ -92,10 +92,7 @@ static unsigned long property_get_size(const char *key) { return value; } -LogBuffer::LogBuffer(LastLogTimes *times) - : mTimes(*times) { - pthread_mutex_init(&mLogElementsLock, NULL); - +void LogBuffer::init() { static const char global_tuneable[] = "persist.logd.size"; // Settings App static const char global_default[] = "ro.logd.size"; // BoardConfig.mk @@ -131,6 +128,13 @@ LogBuffer::LogBuffer(LastLogTimes *times) } } +LogBuffer::LogBuffer(LastLogTimes *times) + : mTimes(*times) { + pthread_mutex_init(&mLogElementsLock, NULL); + + init(); +} + void LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char *msg, unsigned short len) { diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h index b0003ded2..86a2a2a68 100644 --- a/logd/LogBuffer.h +++ b/logd/LogBuffer.h @@ -46,6 +46,7 @@ public: LastLogTimes &mTimes; LogBuffer(LastLogTimes *times); + void init(); void log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, diff --git a/logd/main.cpp b/logd/main.cpp index 243bee4cd..2d799bf7a 100644 --- a/logd/main.cpp +++ b/logd/main.cpp @@ -17,7 +17,10 @@ #include #include #include +#include #include +#include +#include #include #include #include @@ -30,6 +33,7 @@ #include #include +#include #include "private/android_filesystem_config.h" #include "CommandListener.h" @@ -127,17 +131,100 @@ static bool property_get_bool(const char *key, bool def) { return def; } -// Foreground waits for exit of the three main persistent threads that -// are started here. The three threads are created to manage UNIX -// domain client sockets for writing, reading and controlling the user -// space logger. Additional transitory per-client threads are created -// for each reader once they register. -int main() { - bool auditd = property_get_bool("logd.auditd", true); +static sem_t reinit; +static bool reinit_running = false; +static LogBuffer *logBuf = NULL; - int fdDmesg = -1; - if (auditd && property_get_bool("logd.auditd.dmesg", true)) { - fdDmesg = open("/dev/kmsg", O_WRONLY); +static void *reinit_thread_start(void * /*obj*/) { + prctl(PR_SET_NAME, "logd.daemon"); + set_sched_policy(0, SP_BACKGROUND); + + setgid(AID_LOGD); + setuid(AID_LOGD); + + while (reinit_running && !sem_wait(&reinit) && reinit_running) { + // Anything that reads persist. + if (logBuf) { + logBuf->init(); + } + } + + return NULL; +} + +// Serves as a global method to trigger reinitialization +// and as a function that can be provided to signal(). +void reinit_signal_handler(int /*signal*/) { + sem_post(&reinit); +} + +// Remove the static, and use this variable +// globally for debugging if necessary. eg: +// write(fdDmesg, "I am here\n", 10); +static int fdDmesg = -1; + +// Foreground waits for exit of the main persistent threads +// that are started here. The threads are created to manage +// UNIX domain client sockets for writing, reading and +// controlling the user space logger, and for any additional +// logging plugins like auditd and restart control. Additional +// transitory per-client threads are created for each reader. +int main(int argc, char *argv[]) { + fdDmesg = open("/dev/kmsg", O_WRONLY); + + // issue reinit command. KISS argument parsing. + if ((argc > 1) && argv[1] && !strcmp(argv[1], "--reinit")) { + int sock = TEMP_FAILURE_RETRY( + socket_local_client("logd", + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM)); + if (sock < 0) { + return -errno; + } + static const char reinit[] = "reinit"; + ssize_t ret = TEMP_FAILURE_RETRY(write(sock, reinit, sizeof(reinit))); + if (ret < 0) { + return -errno; + } + struct pollfd p; + memset(&p, 0, sizeof(p)); + p.fd = sock; + p.events = POLLIN; + ret = TEMP_FAILURE_RETRY(poll(&p, 1, 100)); + if (ret < 0) { + return -errno; + } + if ((ret == 0) || !(p.revents & POLLIN)) { + return -ETIME; + } + static const char success[] = "success"; + char buffer[sizeof(success) - 1]; + memset(buffer, 0, sizeof(buffer)); + ret = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer))); + if (ret < 0) { + return -errno; + } + return strncmp(buffer, success, sizeof(success) - 1) != 0; + } + + // Reinit Thread + sem_init(&reinit, 0, 0); + pthread_attr_t attr; + if (!pthread_attr_init(&attr)) { + struct sched_param param; + + memset(¶m, 0, sizeof(param)); + pthread_attr_setschedparam(&attr, ¶m); + pthread_attr_setschedpolicy(&attr, SCHED_BATCH); + if (!pthread_attr_setdetachstate(&attr, + PTHREAD_CREATE_DETACHED)) { + pthread_t thread; + reinit_running = true; + if (pthread_create(&thread, &attr, reinit_thread_start, NULL)) { + reinit_running = false; + } + } + pthread_attr_destroy(&attr); } if (drop_privs() != 0) { @@ -153,7 +240,9 @@ int main() { // LogBuffer is the object which is responsible for holding all // log entries. - LogBuffer *logBuf = new LogBuffer(times); + logBuf = new LogBuffer(times); + + signal(SIGHUP, reinit_signal_handler); { char property[PROPERTY_VALUE_MAX]; @@ -195,9 +284,13 @@ int main() { // initiated log messages. New log entries are added to LogBuffer // and LogReader is notified to send updates to connected clients. + bool auditd = property_get_bool("logd.auditd", true); + if (auditd) { + bool dmesg = property_get_bool("logd.auditd.dmesg", true); + // failure is an option ... messages are in dmesg (required by standard) - LogAudit *al = new LogAudit(logBuf, reader, fdDmesg); + LogAudit *al = new LogAudit(logBuf, reader, dmesg ? fdDmesg : -1); int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0); if (len > 0) { @@ -217,11 +310,10 @@ int main() { if (al->startListener()) { delete al; - close(fdDmesg); } } - pause(); + TEMP_FAILURE_RETRY(pause()); + exit(0); } - From 48d06069a8a6be3a968694dad65ce4c11b7bef22 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 11 Mar 2015 14:45:05 -0700 Subject: [PATCH 2/2] init.rc: logd --reinit on changes to persistent properties Bug: 19681572 Change-Id: I3187aa348dae79fa5822ffb7ee9566919a7a04e6 --- rootdir/init.rc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/rootdir/init.rc b/rootdir/init.rc index e3b5db9db..bc36c3e94 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -164,6 +164,7 @@ on property:sys.boot_from_charger_mode=1 # Load properties from /system/ + /factory after fs mount. on load_all_props_action load_all_props + start logd-reinit # Indicate to fw loaders that the relevant mounts are up. on firmware_mounts_complete @@ -430,6 +431,7 @@ on property:vold.decrypt=trigger_reset_main on property:vold.decrypt=trigger_load_persist_props load_persist_props + start logd-reinit on property:vold.decrypt=trigger_post_fs_data trigger post-fs-data @@ -472,6 +474,10 @@ service logd /system/bin/logd socket logdr seqpacket 0666 logd logd socket logdw dgram 0222 logd logd +service logd-reinit /system/bin/logd --reinit + oneshot + disabled + service healthd /sbin/healthd class core critical