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