Timeout for decrypt
Sometimes, usually because of proprietary binaries related to keymaster,
decrypt will hang waiting for the keymaster to initialize forever. This patch
enables a timeout so that we don't get stuck trying to decrypt forever.
A timeout is especially important when dealing with the default password
because the user has no option to cancel when TWRP tries to decrypt.
NOTE: This patch only adds a timeout for FDE. FBE will require some special
handling because we need access to some static data and that data is not
available across a fork.
Special thanks to nkk71 for cleaning up some issues in my patch set.
Change-Id: Iccf2fe769ac27a7dcd6bfebfe7d2e9eddd034308
diff --git a/twrp-functions.cpp b/twrp-functions.cpp
index 3c6c55b..c964357 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -142,6 +142,41 @@
return 0;
}
+int TWFunc::Wait_For_Child_Timeout(pid_t pid, int *status, const string& Child_Name, int timeout) {
+ pid_t retpid = waitpid(pid, status, WNOHANG);
+ for (; retpid == 0 && timeout; --timeout) {
+ sleep(1);
+ retpid = waitpid(pid, status, WNOHANG);
+ }
+ if (retpid == 0 && timeout == 0) {
+ LOGERR("%s took too long, killing process\n", Child_Name.c_str());
+ kill(pid, SIGKILL);
+ int died = 0;
+ for (timeout = 5; retpid == 0 && timeout; --timeout) {
+ sleep(1);
+ retpid = waitpid(pid, status, WNOHANG);
+ }
+ if (retpid)
+ LOGINFO("Child process killed successfully\n");
+ else
+ LOGINFO("Child process took too long to kill, may be a zombie process\n");
+ return -1;
+ } else if (retpid > 0) {
+ if (WIFSIGNALED(*status)) {
+ gui_msg(Msg(msg::kError, "pid_signal={1} process ended with signal: {2}")(Child_Name)(WTERMSIG(*status))); // Seg fault or some other non-graceful termination
+ return -1;
+ }
+ } else if (retpid < 0) { // no PID returned
+ if (errno == ECHILD)
+ LOGERR("%s no child process exist\n", Child_Name.c_str());
+ else {
+ LOGERR("%s Unexpected error %d\n", Child_Name.c_str(), errno);
+ return -1;
+ }
+ }
+ return 0;
+}
+
bool TWFunc::Path_Exists(string Path) {
// Check to see if the Path exists
struct stat st;