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 <errno.h>
21 #include <string.h>
22 #include <unistd.h>
23 
24 #include <string>
25 
26 #ifndef RS_COMPATIBILITY_LIB
27 #include <sys/wait.h>
28 #endif
29 
30 
31 namespace android {
32 namespace renderscript {
33 
rsuCopyString(const char * name)34 const char * rsuCopyString(const char *name) {
35     return rsuCopyString(name, strlen(name));
36 }
37 
rsuCopyString(const char * name,size_t len)38 const char * rsuCopyString(const char *name, size_t len) {
39     char *n = new char[len+1];
40     memcpy(n, name, len);
41     n[len] = 0;
42     return n;
43 }
44 
rsuJoinStrings(int n,const char * const * strs)45 const char* rsuJoinStrings(int n, const char* const* strs) {
46     std::string tmp;
47     for (int i = 0; i < n; i++) {
48         if (i > 0) {
49             tmp.append(" ");
50         }
51         tmp.append(strs[i]);
52     }
53     return strndup(tmp.c_str(), tmp.size());
54 }
55 
56 #ifndef RS_COMPATIBILITY_LIB
rsuExecuteCommand(const char * exe,int nArgs,const char * const * args)57 bool rsuExecuteCommand(const char *exe, int nArgs, const char * const *args) {
58     std::unique_ptr<const char> joined(rsuJoinStrings(nArgs, args));
59     ALOGV("Invoking %s with args '%s'", exe, joined.get());
60 
61     pid_t pid = fork();
62 
63     switch (pid) {
64     case -1: {  // Error occurred (we attempt no recovery)
65         ALOGE("Fork of \"%s\" failed with error %s", exe, strerror(errno));
66         return false;
67     }
68     case 0: {  // Child process
69         // No (direct or indirect) call to malloc between fork and exec.  It is
70         // possible that a different thread holds the heap lock before the fork.
71 
72         // ProcessManager in libcore can reap unclaimed SIGCHLDs in its process
73         // group.  To ensure that the exit signal is not caught by
74         // ProcessManager and instead sent to libRS, set the child's PGID to its
75         // PID.
76         setpgid(0, 0);
77 
78         execv(exe, (char * const *)args);
79 
80         ALOGE("execv() failed: %s", strerror(errno));
81         abort();
82         return false;
83     }
84     default: {  // Parent process (actual driver)
85         // Wait on child process to finish execution.
86         int status = 0;
87         pid_t w = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0));
88         if (w == -1) {
89             ALOGE("Waitpid of \"%s\" failed with error %s", exe,
90                   strerror(errno));
91             return false;
92         }
93 
94         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
95             return true;
96         }
97 
98         ALOGE("Child process \"%s\" terminated with status %d", exe, status);
99         return false;
100     }
101     }
102 }
103 #endif // RS_COMPATIBILITY_LIB
104 
105 // Implementation of property_get from libcutils
property_get(const char * key,char * value,const char * default_value)106 int property_get(const char *key, char *value, const char *default_value) {
107     int len;
108     len = __system_property_get(key, value);
109     if (len > 0) {
110         return len;
111     }
112 
113     if (default_value) {
114         len = strlen(default_value);
115         memcpy(value, default_value, len + 1);
116     }
117     return len;
118 }
119 
120 } // namespace renderscript
121 } // namespace android
122