1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "rsUtils.h"
18 #include "rsCppUtils.h"
19 
20 #include <string>
21 
22 #include <string.h>
23 
24 #ifndef RS_COMPATIBILITY_LIB
25 #include <sys/wait.h>
26 #endif
27 
28 namespace android {
29 namespace renderscript {
30 
rsuCopyString(const char * name)31 const char * rsuCopyString(const char *name) {
32     return rsuCopyString(name, strlen(name));
33 }
34 
rsuCopyString(const char * name,size_t len)35 const char * rsuCopyString(const char *name, size_t len) {
36     char *n = new char[len+1];
37     memcpy(n, name, len);
38     n[len] = 0;
39     return n;
40 }
41 
rsuJoinStrings(int n,const char * const * strs)42 const char* rsuJoinStrings(int n, const char* const* strs) {
43     std::string tmp;
44     for (int i = 0; i < n; i++) {
45         if (i > 0) {
46             tmp.append(" ");
47         }
48         tmp.append(strs[i]);
49     }
50     return strndup(tmp.c_str(), tmp.size());
51 }
52 
53 #ifndef RS_COMPATIBILITY_LIB
rsuExecuteCommand(const char * exe,int nArgs,const char * const * args)54 bool rsuExecuteCommand(const char *exe, int nArgs, const char * const *args) {
55     std::unique_ptr<const char> joined(rsuJoinStrings(nArgs, args));
56     ALOGV("Invoking %s with args '%s'", exe, joined.get());
57 
58     pid_t pid = fork();
59 
60     switch (pid) {
61     case -1: {  // Error occurred (we attempt no recovery)
62         ALOGE("Fork of \"%s\" failed with error %s", exe, strerror(errno));
63         return false;
64     }
65     case 0: {  // Child process
66         // No (direct or indirect) call to malloc between fork and exec.  It is
67         // possible that a different thread holds the heap lock before the fork.
68 
69         // ProcessManager in libcore can reap unclaimed SIGCHLDs in its process
70         // group.  To ensure that the exit signal is not caught by
71         // ProcessManager and instead sent to libRS, set the child's PGID to its
72         // PID.
73         setpgid(0, 0);
74 
75         execv(exe, (char * const *)args);
76 
77         ALOGE("execv() failed: %s", strerror(errno));
78         abort();
79         return false;
80     }
81     default: {  // Parent process (actual driver)
82         // Wait on child process to finish execution.
83         int status = 0;
84         pid_t w = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
85         if (w == -1) {
86             ALOGE("Waitpid of \"%s\" failed with error %s", exe,
87                   strerror(errno));
88             return false;
89         }
90 
91         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
92             return true;
93         }
94 
95         ALOGE("Child process \"%s\" terminated with status %d", exe, status);
96         return false;
97     }
98     }
99 }
100 #endif // RS_COMPATIBILITY_LIB
101 
102 }
103 }
104