1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "platform/globals.h"
6#if defined(HOST_OS_ANDROID)
7
8#include "bin/platform.h"
9
10#include <errno.h> // NOLINT
11#include <signal.h> // NOLINT
12#include <string.h> // NOLINT
13#include <sys/resource.h>
14#include <sys/system_properties.h>
15#include <sys/utsname.h> // NOLINT
16#include <unistd.h> // NOLINT
17
18#include "bin/console.h"
19#include "bin/file.h"
20
21namespace dart {
22namespace bin {
23
24const char* Platform::executable_name_ = NULL;
25char* Platform::resolved_executable_name_ = NULL;
26int Platform::script_index_ = 1;
27char** Platform::argv_ = NULL;
28
29static void segv_handler(int signal, siginfo_t* siginfo, void* context) {
30 Syslog::PrintErr(
31 "\n===== CRASH =====\n"
32 "si_signo=%s(%d), si_code=%d, si_addr=%p\n",
33 strsignal(siginfo->si_signo), siginfo->si_signo, siginfo->si_code,
34 siginfo->si_addr);
35 Dart_DumpNativeStackTrace(context);
36 Dart_PrepareToAbort();
37 abort();
38}
39
40bool Platform::Initialize() {
41 // Turn off the signal handler for SIGPIPE as it causes the process
42 // to terminate on writing to a closed pipe. Without the signal
43 // handler error EPIPE is set instead.
44 struct sigaction act = {};
45 act.sa_handler = SIG_IGN;
46 if (sigaction(SIGPIPE, &act, 0) != 0) {
47 perror("Setting signal handler failed");
48 return false;
49 }
50
51 // tcsetattr raises SIGTTOU if we try to set console attributes when
52 // backgrounded, which suspends the process. Ignoring the signal prevents
53 // us from being suspended and lets us fail gracefully instead.
54 sigset_t signal_mask;
55 sigemptyset(&signal_mask);
56 sigaddset(&signal_mask, SIGTTOU);
57 if (sigprocmask(SIG_BLOCK, &signal_mask, NULL) < 0) {
58 perror("Setting signal handler failed");
59 return false;
60 }
61
62 act.sa_flags = SA_SIGINFO;
63 act.sa_sigaction = &segv_handler;
64 if (sigemptyset(&act.sa_mask) != 0) {
65 perror("sigemptyset() failed.");
66 return false;
67 }
68 if (sigaddset(&act.sa_mask, SIGPROF) != 0) {
69 perror("sigaddset() failed");
70 return false;
71 }
72 if (sigaction(SIGSEGV, &act, NULL) != 0) {
73 perror("sigaction() failed.");
74 return false;
75 }
76 if (sigaction(SIGBUS, &act, NULL) != 0) {
77 perror("sigaction() failed.");
78 return false;
79 }
80 if (sigaction(SIGTRAP, &act, NULL) != 0) {
81 perror("sigaction() failed.");
82 return false;
83 }
84 if (sigaction(SIGILL, &act, NULL) != 0) {
85 perror("sigaction() failed.");
86 return false;
87 }
88 return true;
89}
90
91int Platform::NumberOfProcessors() {
92 return sysconf(_SC_NPROCESSORS_ONLN);
93}
94
95const char* Platform::OperatingSystem() {
96 return "android";
97}
98
99const char* Platform::OperatingSystemVersion() {
100 char os_version[PROP_VALUE_MAX + 1];
101 int os_version_length =
102 __system_property_get("ro.build.display.id", os_version);
103 if (os_version_length == 0) {
104 return NULL;
105 }
106 ASSERT(os_version_length <= PROP_VALUE_MAX);
107 char* result = reinterpret_cast<char*>(
108 Dart_ScopeAllocate((os_version_length + 1) * sizeof(result)));
109 strncpy(result, os_version, (os_version_length + 1));
110 return result;
111}
112
113const char* Platform::LibraryPrefix() {
114 return "lib";
115}
116
117const char* Platform::LibraryExtension() {
118 return "so";
119}
120
121const char* Platform::LocaleName() {
122 char* lang = getenv("LANG");
123 if (lang == NULL) {
124 return "en_US";
125 }
126 return lang;
127}
128
129bool Platform::LocalHostname(char* buffer, intptr_t buffer_length) {
130 return gethostname(buffer, buffer_length) == 0;
131}
132
133char** Platform::Environment(intptr_t* count) {
134 // Using environ directly is only safe as long as we do not
135 // provide access to modifying environment variables.
136 intptr_t i = 0;
137 char** tmp = environ;
138 while (*(tmp++) != NULL) {
139 i++;
140 }
141 *count = i;
142 char** result;
143 result = reinterpret_cast<char**>(Dart_ScopeAllocate(i * sizeof(*result)));
144 for (intptr_t current = 0; current < i; current++) {
145 result[current] = environ[current];
146 }
147 return result;
148}
149
150const char* Platform::GetExecutableName() {
151 return executable_name_;
152}
153
154const char* Platform::ResolveExecutablePath() {
155 return File::ReadLink("/proc/self/exe");
156}
157
158intptr_t Platform::ResolveExecutablePathInto(char* result, size_t result_size) {
159 return File::ReadLinkInto("/proc/self/exe", result, result_size);
160}
161
162void Platform::Exit(int exit_code) {
163 Console::RestoreConfig();
164 Dart_PrepareToAbort();
165 exit(exit_code);
166}
167
168void Platform::SetCoreDumpResourceLimit(int value) {
169 rlimit limit = {static_cast<rlim_t>(value), static_cast<rlim_t>(value)};
170 setrlimit(RLIMIT_CORE, &limit);
171}
172
173} // namespace bin
174} // namespace dart
175
176#endif // defined(HOST_OS_ANDROID)
177