init: add stdio_to_kmsg option
Some services are not native android services and therefore don't log via the normal mechanisms. This gives developers an option to have their stdout/stderr logs sent directly to kmsg. Test: see test prints to kernel log Change-Id: I7973ea74d5cab3a90c2cd9a3d5de2266439d0c01
This commit is contained in:
parent
03642ad8b8
commit
f74b7f5756
5 changed files with 34 additions and 5 deletions
|
@ -170,6 +170,8 @@ runs the service.
|
|||
be changed by setting the "androidboot.console" kernel parameter. In
|
||||
all cases the leading "/dev/" should be omitted, so "/dev/tty0" would be
|
||||
specified as just "console tty0".
|
||||
This option connects stdin, stdout, and stderr to the console. It is mutually exclusive with the
|
||||
stdio_to_kmsg option, which only connects stdout and stderr to kmsg.
|
||||
|
||||
`critical`
|
||||
> This is a device-critical service. If it exits more than four times in
|
||||
|
@ -313,6 +315,13 @@ runs the service.
|
|||
seclabel or computed based on the service executable file security context.
|
||||
For native executables see libcutils android\_get\_control\_socket().
|
||||
|
||||
`stdio_to_kmsg`
|
||||
> Redirect stdout and stderr to /dev/kmsg_debug. This is useful for services that do not use native
|
||||
Android logging during early boot and whose logs messages we want to capture. This is only enabled
|
||||
when /dev/kmsg_debug is enabled, which is only enabled on userdebug and eng builds.
|
||||
This is mutually exclusive with the console option, which additionally connects stdin to the
|
||||
given console.
|
||||
|
||||
`timeout_period <seconds>`
|
||||
> Provide a timeout after which point the service will be killed. The oneshot keyword is respected
|
||||
here, so oneshot services do not automatically restart, however all other services will.
|
||||
|
|
|
@ -83,6 +83,9 @@ Result<void> ServiceParser::ParseClass(std::vector<std::string>&& args) {
|
|||
}
|
||||
|
||||
Result<void> ServiceParser::ParseConsole(std::vector<std::string>&& args) {
|
||||
if (service_->proc_attr_.stdio_to_kmsg) {
|
||||
return Error() << "'console' and 'stdio_to_kmsg' are mutually exclusive";
|
||||
}
|
||||
service_->flags_ |= SVC_CONSOLE;
|
||||
service_->proc_attr_.console = args.size() > 1 ? "/dev/" + args[1] : "";
|
||||
return {};
|
||||
|
@ -429,6 +432,14 @@ Result<void> ServiceParser::ParseSocket(std::vector<std::string>&& args) {
|
|||
return {};
|
||||
}
|
||||
|
||||
Result<void> ServiceParser::ParseStdioToKmsg(std::vector<std::string>&& args) {
|
||||
if (service_->flags_ & SVC_CONSOLE) {
|
||||
return Error() << "'stdio_to_kmsg' and 'console' are mutually exclusive";
|
||||
}
|
||||
service_->proc_attr_.stdio_to_kmsg = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
// name type
|
||||
Result<void> ServiceParser::ParseFile(std::vector<std::string>&& args) {
|
||||
if (args[2] != "r" && args[2] != "w" && args[2] != "rw") {
|
||||
|
@ -514,6 +525,7 @@ const KeywordMap<ServiceParser::OptionParser>& ServiceParser::GetParserMap() con
|
|||
{"shutdown", {1, 1, &ServiceParser::ParseShutdown}},
|
||||
{"sigstop", {0, 0, &ServiceParser::ParseSigstop}},
|
||||
{"socket", {3, 6, &ServiceParser::ParseSocket}},
|
||||
{"stdio_to_kmsg", {0, 0, &ServiceParser::ParseStdioToKmsg}},
|
||||
{"timeout_period", {1, 1, &ServiceParser::ParseTimeoutPeriod}},
|
||||
{"updatable", {0, 0, &ServiceParser::ParseUpdatable}},
|
||||
{"user", {1, 1, &ServiceParser::ParseUser}},
|
||||
|
|
|
@ -75,6 +75,7 @@ class ServiceParser : public SectionParser {
|
|||
Result<void> ParseShutdown(std::vector<std::string>&& args);
|
||||
Result<void> ParseSigstop(std::vector<std::string>&& args);
|
||||
Result<void> ParseSocket(std::vector<std::string>&& args);
|
||||
Result<void> ParseStdioToKmsg(std::vector<std::string>&& args);
|
||||
Result<void> ParseTimeoutPeriod(std::vector<std::string>&& args);
|
||||
Result<void> ParseFile(std::vector<std::string>&& args);
|
||||
Result<void> ParseUser(std::vector<std::string>&& args);
|
||||
|
|
|
@ -16,10 +16,12 @@
|
|||
|
||||
#include "service_utils.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/logging.h>
|
||||
|
@ -121,11 +123,15 @@ Result<void> SetUpPidNamespace(const char* name) {
|
|||
return {};
|
||||
}
|
||||
|
||||
void ZapStdio() {
|
||||
void SetupStdio(bool stdio_to_kmsg) {
|
||||
auto fd = unique_fd{open("/dev/null", O_RDWR | O_CLOEXEC)};
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, 2);
|
||||
dup2(fd, STDIN_FILENO);
|
||||
if (stdio_to_kmsg) {
|
||||
fd.reset(open("/dev/kmsg_debug", O_WRONLY | O_CLOEXEC));
|
||||
if (fd == -1) fd.reset(open("/dev/null", O_WRONLY | O_CLOEXEC));
|
||||
}
|
||||
dup2(fd, STDOUT_FILENO);
|
||||
dup2(fd, STDERR_FILENO);
|
||||
}
|
||||
|
||||
void OpenConsole(const std::string& console) {
|
||||
|
@ -238,7 +244,7 @@ Result<void> SetProcessAttributes(const ProcessAttributes& attr) {
|
|||
if (setpgid(0, getpid()) == -1) {
|
||||
return ErrnoError() << "setpgid failed";
|
||||
}
|
||||
ZapStdio();
|
||||
SetupStdio(attr.stdio_to_kmsg);
|
||||
}
|
||||
|
||||
for (const auto& rlimit : attr.rlimits) {
|
||||
|
|
|
@ -77,6 +77,7 @@ struct ProcessAttributes {
|
|||
gid_t gid;
|
||||
std::vector<gid_t> supp_gids;
|
||||
int priority;
|
||||
bool stdio_to_kmsg;
|
||||
};
|
||||
Result<void> SetProcessAttributes(const ProcessAttributes& attr);
|
||||
|
||||
|
|
Loading…
Reference in a new issue