• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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 <dirent.h>
18 #include <poll.h>
19 #include <sys/prctl.h>
20 #include <sys/ptrace.h>
21 #include <sys/types.h>
22 #include <sys/wait.h>
23 #include <unistd.h>
24 
25 #include <csignal>
26 #include <cstdlib>
27 #include <cstring>
28 #include <iostream>
29 #include <thread>
30 #include <memory>
31 #include <set>
32 #include <string>
33 
34 #include <android-base/file.h>
35 #include <android-base/logging.h>
36 #include <android-base/macros.h>
37 #include <android-base/stringprintf.h>
38 #include <android-base/strings.h>
39 #include <android-base/unique_fd.h>
40 #include <backtrace/Backtrace.h>
41 #include <backtrace/BacktraceMap.h>
42 
43 namespace art {
44 namespace {
45 
46 using android::base::StringPrintf;
47 using android::base::unique_fd;
48 
49 constexpr bool kUseAddr2line = true;
50 
51 namespace timeout_signal {
52 
53 class SignalSet {
54  public:
SignalSet()55   SignalSet() {
56     if (sigemptyset(&set_) == -1) {
57       PLOG(FATAL) << "sigemptyset failed";
58     }
59   }
60 
Add(int signal)61   void Add(int signal) {
62     if (sigaddset(&set_, signal) == -1) {
63       PLOG(FATAL) << "sigaddset " << signal << " failed";
64     }
65   }
66 
Block()67   void Block() {
68     if (pthread_sigmask(SIG_BLOCK, &set_, nullptr) != 0) {
69       PLOG(FATAL) << "pthread_sigmask failed";
70     }
71   }
72 
Wait()73   int Wait() {
74     // Sleep in sigwait() until a signal arrives. gdb causes EINTR failures.
75     int signal_number;
76     int rc = TEMP_FAILURE_RETRY(sigwait(&set_, &signal_number));
77     if (rc != 0) {
78       PLOG(FATAL) << "sigwait failed";
79     }
80     return signal_number;
81   }
82 
83  private:
84   sigset_t set_;
85 };
86 
GetTimeoutSignal()87 int GetTimeoutSignal() {
88   return SIGRTMIN + 2;
89 }
90 
91 }  // namespace timeout_signal
92 
93 namespace addr2line {
94 
95 constexpr const char* kAddr2linePath =
96     "/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.17-4.8/bin/x86_64-linux-addr2line";
97 
FindAddr2line()98 std::unique_ptr<std::string> FindAddr2line() {
99   const char* env_value = getenv("ANDROID_BUILD_TOP");
100   if (env_value != nullptr) {
101     std::string path = std::string(env_value) + kAddr2linePath;
102     if (access(path.c_str(), X_OK) == 0) {
103       return std::make_unique<std::string>(path);
104     }
105   }
106 
107   {
108     std::string path = std::string(".") + kAddr2linePath;
109     if (access(path.c_str(), X_OK) == 0) {
110       return std::make_unique<std::string>(path);
111     }
112   }
113 
114   {
115     using android::base::Dirname;
116 
117     std::string exec_dir = android::base::GetExecutableDirectory();
118     std::string derived_top = Dirname(Dirname(Dirname(Dirname(exec_dir))));
119     std::string path = derived_top + kAddr2linePath;
120     if (access(path.c_str(), X_OK) == 0) {
121       return std::make_unique<std::string>(path);
122     }
123   }
124 
125   constexpr const char* kHostAddr2line = "/usr/bin/addr2line";
126   if (access(kHostAddr2line, F_OK) == 0) {
127     return std::make_unique<std::string>(kHostAddr2line);
128   }
129 
130   return nullptr;
131 }
132 
133 // The state of an open pipe to addr2line. In "server" mode, addr2line takes input on stdin
134 // and prints the result to stdout. This struct keeps the state of the open connection.
135 struct Addr2linePipe {
Addr2linePipeart::__anonbb930b670111::addr2line::Addr2linePipe136   Addr2linePipe(int in_fd, int out_fd, const std::string& file_name, pid_t pid)
137       : in(in_fd), out(out_fd), file(file_name), child_pid(pid), odd(true) {}
138 
~Addr2linePipeart::__anonbb930b670111::addr2line::Addr2linePipe139   ~Addr2linePipe() {
140     kill(child_pid, SIGKILL);
141   }
142 
143   unique_fd in;      // The file descriptor that is connected to the output of addr2line.
144   unique_fd out;     // The file descriptor that is connected to the input of addr2line.
145 
146   const std::string file;     // The file addr2line is working on, so that we know when to close
147                               // and restart.
148   const pid_t child_pid;      // The pid of the child, which we should kill when we're done.
149   bool odd;                   // Print state for indentation of lines.
150 };
151 
Connect(const std::string & name,const char * args[])152 std::unique_ptr<Addr2linePipe> Connect(const std::string& name, const char* args[]) {
153   int caller_to_addr2line[2];
154   int addr2line_to_caller[2];
155 
156   if (pipe(caller_to_addr2line) == -1) {
157     return nullptr;
158   }
159   if (pipe(addr2line_to_caller) == -1) {
160     close(caller_to_addr2line[0]);
161     close(caller_to_addr2line[1]);
162     return nullptr;
163   }
164 
165   pid_t pid = fork();
166   if (pid == -1) {
167     close(caller_to_addr2line[0]);
168     close(caller_to_addr2line[1]);
169     close(addr2line_to_caller[0]);
170     close(addr2line_to_caller[1]);
171     return nullptr;
172   }
173 
174   if (pid == 0) {
175     dup2(caller_to_addr2line[0], STDIN_FILENO);
176     dup2(addr2line_to_caller[1], STDOUT_FILENO);
177 
178     close(caller_to_addr2line[0]);
179     close(caller_to_addr2line[1]);
180     close(addr2line_to_caller[0]);
181     close(addr2line_to_caller[1]);
182 
183     execv(args[0], const_cast<char* const*>(args));
184     exit(1);
185   } else {
186     close(caller_to_addr2line[0]);
187     close(addr2line_to_caller[1]);
188     return std::make_unique<Addr2linePipe>(addr2line_to_caller[0],
189                                            caller_to_addr2line[1],
190                                            name,
191                                            pid);
192   }
193 }
194 
WritePrefix(std::ostream & os,const char * prefix,bool odd)195 void WritePrefix(std::ostream& os, const char* prefix, bool odd) {
196   if (prefix != nullptr) {
197     os << prefix;
198   }
199   os << "  ";
200   if (!odd) {
201     os << " ";
202   }
203 }
204 
Drain(size_t expected,const char * prefix,std::unique_ptr<Addr2linePipe> * pipe,std::ostream & os)205 void Drain(size_t expected,
206            const char* prefix,
207            std::unique_ptr<Addr2linePipe>* pipe /* inout */,
208            std::ostream& os) {
209   DCHECK(pipe != nullptr);
210   DCHECK(pipe->get() != nullptr);
211   int in = pipe->get()->in.get();
212   DCHECK_GE(in, 0);
213 
214   bool prefix_written = false;
215 
216   for (;;) {
217     constexpr uint32_t kWaitTimeExpectedMilli = 500;
218     constexpr uint32_t kWaitTimeUnexpectedMilli = 50;
219 
220     int timeout = expected > 0 ? kWaitTimeExpectedMilli : kWaitTimeUnexpectedMilli;
221     struct pollfd read_fd{in, POLLIN, 0};
222     int retval = TEMP_FAILURE_RETRY(poll(&read_fd, 1, timeout));
223     if (retval == -1) {
224       // An error occurred.
225       pipe->reset();
226       return;
227     }
228 
229     if (retval == 0) {
230       // Timeout.
231       return;
232     }
233 
234     if (!(read_fd.revents & POLLIN)) {
235       // addr2line call exited.
236       pipe->reset();
237       return;
238     }
239 
240     constexpr size_t kMaxBuffer = 128;  // Relatively small buffer. Should be OK as we're on an
241     // alt stack, but just to be sure...
242     char buffer[kMaxBuffer];
243     memset(buffer, 0, kMaxBuffer);
244     int bytes_read = TEMP_FAILURE_RETRY(read(in, buffer, kMaxBuffer - 1));
245     if (bytes_read <= 0) {
246       // This should not really happen...
247       pipe->reset();
248       return;
249     }
250     buffer[bytes_read] = '\0';
251 
252     char* tmp = buffer;
253     while (*tmp != 0) {
254       if (!prefix_written) {
255         WritePrefix(os, prefix, (*pipe)->odd);
256         prefix_written = true;
257       }
258       char* new_line = strchr(tmp, '\n');
259       if (new_line == nullptr) {
260         os << tmp;
261 
262         break;
263       } else {
264         os << std::string(tmp, new_line - tmp + 1);
265 
266         tmp = new_line + 1;
267         prefix_written = false;
268         (*pipe)->odd = !(*pipe)->odd;
269 
270         if (expected > 0) {
271           expected--;
272         }
273       }
274     }
275   }
276 }
277 
Addr2line(const std::string & addr2line,const std::string & map_src,uintptr_t offset,std::ostream & os,const char * prefix,std::unique_ptr<Addr2linePipe> * pipe)278 void Addr2line(const std::string& addr2line,
279                const std::string& map_src,
280                uintptr_t offset,
281                std::ostream& os,
282                const char* prefix,
283                std::unique_ptr<Addr2linePipe>* pipe /* inout */) {
284   DCHECK(pipe != nullptr);
285 
286   if (map_src == "[vdso]" || android::base::EndsWith(map_src, ".vdex")) {
287     // addr2line will not work on the vdso.
288     // vdex files are special frames injected for the interpreter
289     // so they don't have any line number information available.
290     return;
291   }
292 
293   if (*pipe == nullptr || (*pipe)->file != map_src) {
294     if (*pipe != nullptr) {
295       Drain(0, prefix, pipe, os);
296     }
297     pipe->reset();  // Close early.
298 
299     const char* args[] = {
300         addr2line.c_str(),
301         "--functions",
302         "--inlines",
303         "--demangle",
304         "-e",
305         map_src.c_str(),
306         nullptr
307     };
308     *pipe = Connect(map_src, args);
309   }
310 
311   Addr2linePipe* pipe_ptr = pipe->get();
312   if (pipe_ptr == nullptr) {
313     // Failed...
314     return;
315   }
316 
317   // Send the offset.
318   const std::string hex_offset = StringPrintf("%zx\n", offset);
319 
320   if (!android::base::WriteFully(pipe_ptr->out.get(), hex_offset.data(), hex_offset.length())) {
321     // Error. :-(
322     pipe->reset();
323     return;
324   }
325 
326   // Now drain (expecting two lines).
327   Drain(2U, prefix, pipe, os);
328 }
329 
330 }  // namespace addr2line
331 
332 namespace ptrace {
333 
PtraceSiblings(pid_t pid)334 std::set<pid_t> PtraceSiblings(pid_t pid) {
335   std::set<pid_t> ret;
336   std::string task_path = android::base::StringPrintf("/proc/%d/task", pid);
337 
338   std::unique_ptr<DIR, int (*)(DIR*)> d(opendir(task_path.c_str()), closedir);
339 
340   // Bail early if the task directory cannot be opened.
341   if (d == nullptr) {
342     PLOG(ERROR) << "Failed to scan task folder";
343     return ret;
344   }
345 
346   struct dirent* de;
347   while ((de = readdir(d.get())) != nullptr) {
348     // Ignore "." and "..".
349     if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
350       continue;
351     }
352 
353     char* end;
354     pid_t tid = strtoul(de->d_name, &end, 10);
355     if (*end) {
356       continue;
357     }
358 
359     if (tid == pid) {
360       continue;
361     }
362 
363     if (::ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
364       PLOG(ERROR) << "Failed to attach to tid " << tid;
365       continue;
366     }
367 
368     ret.insert(tid);
369   }
370   return ret;
371 }
372 
DumpABI(pid_t forked_pid)373 void DumpABI(pid_t forked_pid) {
374   enum class ABI { kArm, kArm64, kMips, kMips64, kX86, kX86_64 };
375 #if defined(__arm__)
376   constexpr ABI kDumperABI = ABI::kArm;
377 #elif defined(__aarch64__)
378   constexpr ABI kDumperABI = ABI::kArm64;
379 #elif defined(__mips__) && !defined(__LP64__)
380   constexpr ABI kDumperABI = ABI::kMips;
381 #elif defined(__mips__) && defined(__LP64__)
382   constexpr ABI kDumperABI = ABI::kMips64;
383 #elif defined(__i386__)
384   constexpr ABI kDumperABI = ABI::kX86;
385 #elif defined(__x86_64__)
386   constexpr ABI kDumperABI = ABI::kX86_64;
387 #else
388 #error Unsupported architecture
389 #endif
390 
391   char data[1024];  // Should be more than enough.
392   struct iovec io_vec;
393   io_vec.iov_base = &data;
394   io_vec.iov_len = 1024;
395   ABI to_print;
396   if (0 != ::ptrace(PTRACE_GETREGSET, forked_pid, /* NT_PRSTATUS */ 1, &io_vec)) {
397     LOG(ERROR) << "Could not get registers to determine abi.";
398     // Use 64-bit as default.
399     switch (kDumperABI) {
400       case ABI::kArm:
401       case ABI::kArm64:
402         to_print = ABI::kArm64;
403         break;
404       case ABI::kMips:
405       case ABI::kMips64:
406         to_print = ABI::kMips64;
407         break;
408       case ABI::kX86:
409       case ABI::kX86_64:
410         to_print = ABI::kX86_64;
411         break;
412       default:
413         __builtin_unreachable();
414     }
415   } else {
416     // Check the length of the data. Assume that it's the same arch as the tool.
417     switch (kDumperABI) {
418       case ABI::kArm:
419       case ABI::kArm64:
420         to_print = io_vec.iov_len == 18 * sizeof(uint32_t) ? ABI::kArm : ABI::kArm64;
421         break;
422       case ABI::kMips:
423       case ABI::kMips64:
424         to_print = ABI::kMips64;  // TODO Figure out how this should work.
425         break;
426       case ABI::kX86:
427       case ABI::kX86_64:
428         to_print = io_vec.iov_len == 17 * sizeof(uint32_t) ? ABI::kX86 : ABI::kX86_64;
429         break;
430       default:
431         __builtin_unreachable();
432     }
433   }
434   std::string abi_str;
435   switch (to_print) {
436     case ABI::kArm:
437       abi_str = "arm";
438       break;
439     case ABI::kArm64:
440       abi_str = "arm64";
441       break;
442     case ABI::kMips:
443       abi_str = "mips";
444       break;
445     case ABI::kMips64:
446       abi_str = "mips64";
447       break;
448     case ABI::kX86:
449       abi_str = "x86";
450       break;
451     case ABI::kX86_64:
452       abi_str = "x86_64";
453       break;
454   }
455   std::cerr << "ABI: '" << abi_str << "'" << std::endl;
456 }
457 
458 }  // namespace ptrace
459 
460 template <typename T>
WaitLoop(uint32_t max_wait_micros,const T & handler)461 bool WaitLoop(uint32_t max_wait_micros, const T& handler) {
462   constexpr uint32_t kWaitMicros = 10;
463   const size_t kMaxLoopCount = max_wait_micros / kWaitMicros;
464 
465   for (size_t loop_count = 1; loop_count <= kMaxLoopCount; ++loop_count) {
466     bool ret;
467     if (handler(&ret)) {
468       return ret;
469     }
470     usleep(kWaitMicros);
471   }
472   return false;
473 }
474 
WaitForMainSigStop(const std::atomic<bool> & saw_wif_stopped_for_main)475 bool WaitForMainSigStop(const std::atomic<bool>& saw_wif_stopped_for_main) {
476   auto handler = [&](bool* res) {
477     if (saw_wif_stopped_for_main) {
478       *res = true;
479       return true;
480     }
481     return false;
482   };
483   constexpr uint32_t kMaxWaitMicros = 30 * 1000 * 1000;  // 30s wait.
484   return WaitLoop(kMaxWaitMicros, handler);
485 }
486 
WaitForSigStopped(pid_t pid,uint32_t max_wait_micros)487 bool WaitForSigStopped(pid_t pid, uint32_t max_wait_micros) {
488   auto handler = [&](bool* res) {
489     int status;
490     pid_t rc = TEMP_FAILURE_RETRY(waitpid(pid, &status, WNOHANG));
491     if (rc == -1) {
492       PLOG(ERROR) << "Failed to waitpid for " << pid;
493       *res = false;
494       return true;
495     }
496     if (rc == pid) {
497       if (!(WIFSTOPPED(status))) {
498         LOG(ERROR) << "Did not get expected stopped signal for " << pid;
499         *res = false;
500       } else {
501         *res = true;
502       }
503       return true;
504     }
505     return false;
506   };
507   return WaitLoop(max_wait_micros, handler);
508 }
509 
510 #ifdef __LP64__
511 constexpr bool kIs64Bit = true;
512 #else
513 constexpr bool kIs64Bit = false;
514 #endif
515 
DumpThread(pid_t pid,pid_t tid,const std::string * addr2line_path,const char * prefix,BacktraceMap * map)516 void DumpThread(pid_t pid,
517                 pid_t tid,
518                 const std::string* addr2line_path,
519                 const char* prefix,
520                 BacktraceMap* map) {
521   // Use std::cerr to avoid the LOG prefix.
522   std::cerr << std::endl << "=== pid: " << pid << " tid: " << tid << " ===" << std::endl;
523 
524   constexpr uint32_t kMaxWaitMicros = 1000 * 1000;  // 1s.
525   if (pid != tid && !WaitForSigStopped(tid, kMaxWaitMicros)) {
526     LOG(ERROR) << "Failed to wait for sigstop on " << tid;
527   }
528 
529   std::unique_ptr<Backtrace> backtrace(Backtrace::Create(pid, tid, map));
530   if (backtrace == nullptr) {
531     LOG(ERROR) << prefix << "(failed to create Backtrace for thread " << tid << ")";
532     return;
533   }
534   backtrace->SetSkipFrames(false);
535   if (!backtrace->Unwind(0, nullptr)) {
536     LOG(ERROR) << prefix << "(backtrace::Unwind failed for thread " << tid
537                << ": " <<  backtrace->GetErrorString(backtrace->GetError()) << ")";
538     return;
539   }
540   if (backtrace->NumFrames() == 0) {
541     LOG(ERROR) << prefix << "(no native stack frames for thread " << tid << ")";
542     return;
543   }
544 
545   std::unique_ptr<addr2line::Addr2linePipe> addr2line_state;
546 
547   for (Backtrace::const_iterator it = backtrace->begin();
548       it != backtrace->end(); ++it) {
549     std::ostringstream oss;
550     oss << prefix << StringPrintf("#%02zu pc ", it->num);
551     bool try_addr2line = false;
552     if (!BacktraceMap::IsValid(it->map)) {
553       oss << StringPrintf(kIs64Bit ? "%016" PRIx64 "  ???" : "%08" PRIx64 "  ???", it->pc);
554     } else {
555       oss << StringPrintf(kIs64Bit ? "%016" PRIx64 "  " : "%08" PRIx64 "  ", it->rel_pc);
556       if (it->map.name.empty()) {
557         oss << StringPrintf("<anonymous:%" PRIx64 ">", it->map.start);
558       } else {
559         oss << it->map.name;
560       }
561       if (it->map.offset != 0) {
562         oss << StringPrintf(" (offset %" PRIx64 ")", it->map.offset);
563       }
564       oss << " (";
565       if (!it->func_name.empty()) {
566         oss << it->func_name;
567         if (it->func_offset != 0) {
568           oss << "+" << it->func_offset;
569         }
570         // Functions found using the gdb jit interface will be in an empty
571         // map that cannot be found using addr2line.
572         if (!it->map.name.empty()) {
573           try_addr2line = true;
574         }
575       } else {
576         oss << "???";
577       }
578       oss << ")";
579     }
580     std::cerr << oss.str() << std::endl;
581     if (try_addr2line && addr2line_path != nullptr) {
582       addr2line::Addr2line(*addr2line_path,
583                            it->map.name,
584                            it->rel_pc,
585                            std::cerr,
586                            prefix,
587                            &addr2line_state);
588     }
589   }
590 
591   if (addr2line_state != nullptr) {
592     addr2line::Drain(0, prefix, &addr2line_state, std::cerr);
593   }
594 }
595 
DumpProcess(pid_t forked_pid,const std::atomic<bool> & saw_wif_stopped_for_main)596 void DumpProcess(pid_t forked_pid, const std::atomic<bool>& saw_wif_stopped_for_main) {
597   LOG(ERROR) << "Timeout for process " << forked_pid;
598 
599   CHECK_EQ(0, ::ptrace(PTRACE_ATTACH, forked_pid, 0, 0));
600   std::set<pid_t> tids = ptrace::PtraceSiblings(forked_pid);
601   tids.insert(forked_pid);
602 
603   ptrace::DumpABI(forked_pid);
604 
605   // Check whether we have and should use addr2line.
606   std::unique_ptr<std::string> addr2line_path;
607   if (kUseAddr2line) {
608     addr2line_path = addr2line::FindAddr2line();
609     if (addr2line_path == nullptr) {
610       LOG(ERROR) << "Did not find usable addr2line";
611     }
612   }
613 
614   if (!WaitForMainSigStop(saw_wif_stopped_for_main)) {
615     LOG(ERROR) << "Did not receive SIGSTOP for pid " << forked_pid;
616   }
617 
618   std::unique_ptr<BacktraceMap> backtrace_map(BacktraceMap::Create(forked_pid));
619   if (backtrace_map == nullptr) {
620     LOG(ERROR) << "Could not create BacktraceMap";
621     return;
622   }
623 
624   for (pid_t tid : tids) {
625     DumpThread(forked_pid, tid, addr2line_path.get(), "  ", backtrace_map.get());
626   }
627 }
628 
629 [[noreturn]]
WaitMainLoop(pid_t forked_pid,std::atomic<bool> * saw_wif_stopped_for_main)630 void WaitMainLoop(pid_t forked_pid, std::atomic<bool>* saw_wif_stopped_for_main) {
631   for (;;) {
632     // Consider switching to waitid to not get woken up for WIFSTOPPED.
633     int status;
634     pid_t res = TEMP_FAILURE_RETRY(waitpid(forked_pid, &status, 0));
635     if (res == -1) {
636       PLOG(FATAL) << "Failure during waitpid";
637       __builtin_unreachable();
638     }
639 
640     if (WIFEXITED(status)) {
641       _exit(WEXITSTATUS(status));
642       __builtin_unreachable();
643     }
644     if (WIFSIGNALED(status)) {
645       _exit(1);
646       __builtin_unreachable();
647     }
648     if (WIFSTOPPED(status)) {
649       *saw_wif_stopped_for_main = true;
650       continue;
651     }
652     if (WIFCONTINUED(status)) {
653       continue;
654     }
655 
656     LOG(FATAL) << "Unknown status " << std::hex << status;
657   }
658 }
659 
660 [[noreturn]]
SetupAndWait(pid_t forked_pid)661 void SetupAndWait(pid_t forked_pid) {
662   timeout_signal::SignalSet signals;
663   signals.Add(timeout_signal::GetTimeoutSignal());
664   signals.Block();
665 
666   std::atomic<bool> saw_wif_stopped_for_main(false);
667 
668   std::thread signal_catcher([&]() {
669     signals.Block();
670     int sig = signals.Wait();
671     CHECK_EQ(sig, timeout_signal::GetTimeoutSignal());
672 
673     DumpProcess(forked_pid, saw_wif_stopped_for_main);
674 
675     // Don't clean up. Just kill the child and exit.
676     kill(forked_pid, SIGKILL);
677     _exit(1);
678   });
679 
680   WaitMainLoop(forked_pid, &saw_wif_stopped_for_main);
681 }
682 
683 }  // namespace
684 }  // namespace art
685 
main(int argc ATTRIBUTE_UNUSED,char ** argv)686 int main(int argc ATTRIBUTE_UNUSED, char** argv) {
687   pid_t orig_ppid = getpid();
688 
689   pid_t pid = fork();
690   if (pid == 0) {
691     if (prctl(PR_SET_PDEATHSIG, SIGTERM) == -1) {
692       _exit(1);
693     }
694 
695     if (getppid() != orig_ppid) {
696       _exit(2);
697     }
698 
699     execvp(argv[1], &argv[1]);
700 
701     _exit(3);
702     __builtin_unreachable();
703   }
704 
705   art::SetupAndWait(pid);
706   __builtin_unreachable();
707 }
708