| /* | |
| * Copyright (C) 2013 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #include "rsUtils.h" | |
| #include "rsCppUtils.h" | |
| #include <string> | |
| #include <string.h> | |
| #ifndef RS_COMPATIBILITY_LIB | |
| #include <sys/wait.h> | |
| #endif | |
| namespace android { | |
| namespace renderscript { | |
| const char * rsuCopyString(const char *name) { | |
| return rsuCopyString(name, strlen(name)); | |
| } | |
| const char * rsuCopyString(const char *name, size_t len) { | |
| char *n = new char[len+1]; | |
| memcpy(n, name, len); | |
| n[len] = 0; | |
| return n; | |
| } | |
| const char* rsuJoinStrings(int n, const char* const* strs) { | |
| std::string tmp; | |
| for (int i = 0; i < n; i++) { | |
| if (i > 0) { | |
| tmp.append(" "); | |
| } | |
| tmp.append(strs[i]); | |
| } | |
| return strndup(tmp.c_str(), tmp.size()); | |
| } | |
| #ifndef RS_COMPATIBILITY_LIB | |
| bool rsuExecuteCommand(const char *exe, int nArgs, const char * const *args) { | |
| std::unique_ptr<const char> joined(rsuJoinStrings(nArgs, args)); | |
| ALOGV("Invoking %s with args '%s'", exe, joined.get()); | |
| pid_t pid = fork(); | |
| switch (pid) { | |
| case -1: { // Error occurred (we attempt no recovery) | |
| ALOGE("Fork of \"%s\" failed with error %s", exe, strerror(errno)); | |
| return false; | |
| } | |
| case 0: { // Child process | |
| // No (direct or indirect) call to malloc between fork and exec. It is | |
| // possible that a different thread holds the heap lock before the fork. | |
| // ProcessManager in libcore can reap unclaimed SIGCHLDs in its process | |
| // group. To ensure that the exit signal is not caught by | |
| // ProcessManager and instead sent to libRS, set the child's PGID to its | |
| // PID. | |
| setpgid(0, 0); | |
| execv(exe, (char * const *)args); | |
| ALOGE("execv() failed: %s", strerror(errno)); | |
| abort(); | |
| return false; | |
| } | |
| default: { // Parent process (actual driver) | |
| // Wait on child process to finish execution. | |
| int status = 0; | |
| pid_t w = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); | |
| if (w == -1) { | |
| ALOGE("Waitpid of \"%s\" failed with error %s", exe, | |
| strerror(errno)); | |
| return false; | |
| } | |
| if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { | |
| return true; | |
| } | |
| ALOGE("Child process \"%s\" terminated with status %d", exe, status); | |
| return false; | |
| } | |
| } | |
| } | |
| #endif // RS_COMPATIBILITY_LIB | |
| } | |
| } |