• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018, 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 "fork.h"
18 
19 #include "log.h"
20 
21 #include <errno.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/wait.h>
25 #include <unistd.h>
26 
forkAndExec(const char * argv[])27 bool forkAndExec(const char* argv[]) {
28     pid_t pid = ::fork();
29     if (pid < 0) {
30         // Failed to fork
31         LOGE("fork() failed: %s", strerror(errno));
32         return false;
33     } else if (pid == 0) {
34         // Child
35         char buffer[32768];
36         size_t offset = 0;
37         for (size_t i = 0; argv[i]; ++i) {
38             offset += snprintf(buffer + offset, sizeof(buffer) - offset,
39                                "%s ", argv[i]);
40         }
41         LOGE("Running '%s'", buffer);
42         execvp(argv[0], const_cast<char* const*>(argv));
43         LOGE("Failed to run '%s': %s", argv[0], strerror(errno));
44         _exit(1);
45     } else {
46         // Parent
47         int status = 0;
48         do {
49             ::waitpid(pid, &status, 0);
50             if (WIFEXITED(status)) {
51                 int exitStatus = WEXITSTATUS(status);
52                 if (exitStatus == 0) {
53                     return true;
54                 }
55                 LOGE("Error: '%s' exited with code: %d", argv[0], exitStatus);
56             } else if (WIFSIGNALED(status)) {
57                 LOGE("Error: '%s' terminated with signal: %d",
58                      argv[0], WTERMSIG(status));
59             }
60             // Other possibilities include being stopped and continued as part
61             // of a trace but we don't really care about that. The important
62             // part is that unless the process explicitly exited or was killed
63             // by a signal we have to keep waiting.
64         } while (!WIFEXITED(status) && !WIFSIGNALED(status));
65         return false;
66     }
67 }
68