Merge "init: add wait_for_prop builtin command" am: d25e4c5819 am: 7f1dbd8f68

am: 6426815ecc

Change-Id: I9a02f6ba2b191d5159a62abc5c2ea77bf22d16fd
This commit is contained in:
Wei Wang 2017-02-02 04:53:47 +00:00 committed by android-build-merger
commit 4d847cbef1
4 changed files with 62 additions and 2 deletions

View file

@ -298,7 +298,8 @@ Commands
> Fork and execute command with the given arguments. The command starts > Fork and execute command with the given arguments. The command starts
after "--" so that an optional security context, user, and supplementary after "--" so that an optional security context, user, and supplementary
groups can be provided. No other commands will be run until this one groups can be provided. No other commands will be run until this one
finishes. _seclabel_ can be a - to denote default. finishes. _seclabel_ can be a - to denote default. Properties are expanded
within _argument_.
`export <name> <value>` `export <name> <value>`
> Set the environment variable _name_ equal to _value_ in the > Set the environment variable _name_ equal to _value_ in the
@ -412,6 +413,11 @@ Commands
or the timeout has been reached. If timeout is not specified it or the timeout has been reached. If timeout is not specified it
currently defaults to five seconds. currently defaults to five seconds.
`wait_for_prop <name> <value>`
> Wait for system property _name_ to be _value_. Properties are expanded
within _value_. If property _name_ is already set to _value_, continue
immediately.
`write <path> <content>` `write <path> <content>`
> Open the file at _path_ and write a string to it with write(2). > Open the file at _path_ and write a string to it with write(2).
If the file does not exist, it will be created. If it does exist, If the file does not exist, it will be created. If it does exist,

View file

@ -1003,6 +1003,29 @@ static int do_wait(const std::vector<std::string>& args) {
return -1; return -1;
} }
static int do_wait_for_prop(const std::vector<std::string>& args) {
const char* name = args[1].c_str();
const char* value = args[2].c_str();
size_t value_len = strlen(value);
if (!is_legal_property_name(name)) {
LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
<< "\") failed: bad name";
return -1;
}
if (value_len >= PROP_VALUE_MAX) {
LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
<< "\") failed: value too long";
return -1;
}
if (!wait_property(name, value)) {
LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value
<< "\") failed: init already in waiting";
return -1;
}
return 0;
}
/* /*
* Callback to make a directory from the ext4 code * Callback to make a directory from the ext4 code
*/ */
@ -1074,6 +1097,7 @@ BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
{"verity_load_state", {0, 0, do_verity_load_state}}, {"verity_load_state", {0, 0, do_verity_load_state}},
{"verity_update_state", {0, 0, do_verity_update_state}}, {"verity_update_state", {0, 0, do_verity_update_state}},
{"wait", {1, 2, do_wait}}, {"wait", {1, 2, do_wait}},
{"wait_for_prop", {2, 2, do_wait_for_prop}},
{"write", {2, 2, do_write}}, {"write", {2, 2, do_write}},
}; };
return builtin_functions; return builtin_functions;

View file

@ -87,6 +87,10 @@ bool waiting_for_exec = false;
static int epoll_fd = -1; static int epoll_fd = -1;
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::string wait_prop_name;
static std::string wait_prop_value;
void register_epoll_handler(int fd, void (*fn)()) { void register_epoll_handler(int fd, void (*fn)()) {
epoll_event ev; epoll_event ev;
ev.events = EPOLLIN; ev.events = EPOLLIN;
@ -128,10 +132,34 @@ int add_environment(const char *key, const char *val)
return -1; return -1;
} }
bool wait_property(const char *name, const char *value)
{
if (waiting_for_prop) {
return false;
}
if (property_get(name) != value) {
// Current property value is not equal to expected value
wait_prop_name = name;
wait_prop_value = value;
waiting_for_prop.reset(new Timer());
} else {
LOG(INFO) << "wait_property(\"" << name << "\", \"" << value << "\"): already set";
}
return true;
}
void property_changed(const char *name, const char *value) void property_changed(const char *name, const char *value)
{ {
if (property_triggers_enabled) if (property_triggers_enabled)
ActionManager::GetInstance().QueuePropertyTrigger(name, value); ActionManager::GetInstance().QueuePropertyTrigger(name, value);
if (waiting_for_prop) {
if (wait_prop_name == name && wait_prop_value == value) {
wait_prop_name.clear();
wait_prop_value.clear();
LOG(INFO) << "Wait for property took " << *waiting_for_prop;
waiting_for_prop.reset();
}
}
} }
static void restart_processes() static void restart_processes()
@ -876,7 +904,7 @@ int main(int argc, char** argv) {
am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers"); am.QueueBuiltinAction(queue_property_triggers_action, "queue_property_triggers");
while (true) { while (true) {
if (!waiting_for_exec) { if (!(waiting_for_exec || waiting_for_prop)) {
am.ExecuteOneCommand(); am.ExecuteOneCommand();
restart_processes(); restart_processes();
} }

View file

@ -36,4 +36,6 @@ void register_epoll_handler(int fd, void (*fn)());
int add_environment(const char* key, const char* val); int add_environment(const char* key, const char* val);
bool wait_property(const char *name, const char *value);
#endif /* _INIT_INIT_H */ #endif /* _INIT_INIT_H */