Home | History | Annotate | Download | only in rs
      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 
     31 const char * rsuCopyString(const char *name) {
     32     return rsuCopyString(name, strlen(name));
     33 }
     34 
     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 
     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
     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