Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
process.cc
Go to the documentation of this file.
1// Copyright (c) 2013, 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 "bin/process.h"
6
7#include "bin/dartutils.h"
8#include "bin/io_buffer.h"
9#include "bin/namespace.h"
10#include "bin/platform.h"
11#include "bin/socket.h"
12#include "bin/utils.h"
13#include "platform/syslog.h"
14
15#include "include/dart_api.h"
16
17namespace dart {
18namespace bin {
19
20static constexpr int kProcessIdNativeField = 0;
21
22// Extract an array of C strings from a list of Dart strings.
23static char** ExtractCStringList(Dart_Handle strings,
24 Dart_Handle status_handle,
25 const char* error_msg,
26 intptr_t* length) {
27 static constexpr intptr_t kMaxArgumentListLength = 1024 * 1024;
28 ASSERT(Dart_IsList(strings));
29 intptr_t len = 0;
30 Dart_Handle result = Dart_ListLength(strings, &len);
32 // Protect against user-defined list implementations that can have
33 // arbitrary length.
34 if ((len < 0) || (len > kMaxArgumentListLength)) {
35 result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
37 result = DartUtils::SetStringField(status_handle, "_errorMessage",
38 "Max argument list length exceeded");
40 return nullptr;
41 }
42 *length = len;
43 char** string_args;
44 string_args =
45 reinterpret_cast<char**>(Dart_ScopeAllocate(len * sizeof(*string_args)));
46 for (int i = 0; i < len; i++) {
47 Dart_Handle arg = Dart_ListGetAt(strings, i);
48 ThrowIfError(arg);
49 if (!Dart_IsString(arg)) {
50 result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
52 result =
53 DartUtils::SetStringField(status_handle, "_errorMessage", error_msg);
55 return nullptr;
56 }
57 string_args[i] = const_cast<char*>(DartUtils::GetStringValue(arg));
58 }
59 return string_args;
60}
61
63 return (mode == kNormal) || (mode == kInheritStdio);
64}
65
67 return (mode == kNormal) || (mode == kDetachedWithStdio);
68}
69
71 for (intptr_t i = 1; i <= kLastSignal; i++) {
73 }
74}
75
78 intptr_t process_stdin;
79 intptr_t process_stdout;
80 intptr_t process_stderr;
81 intptr_t exit_event;
83 Dart_Handle status_handle = Dart_GetNativeArgument(args, 11);
84 Dart_Handle path_handle = Dart_GetNativeArgument(args, 2);
86
87#if DART_HOST_OS_IOS
88 // Do the iOS check here because the return value of Process::Start is
89 // interpreted as a error with 0 meaning success while `ProcessException`
90 // (which will be constructed with `_errorCode`) interprets 0 to mean that
91 // no OS error code was available.
92 result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
95 status_handle, "_errorMessage",
96 "Starting new processes is not supported on iOS");
99 return;
100#endif
101
102 // The Dart code verifies that the path implements the String
103 // interface. However, only builtin Strings are handled by
104 // GetStringValue.
105 if (!Dart_IsString(path_handle)) {
106 result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
108 result = DartUtils::SetStringField(status_handle, "_errorMessage",
109 "Path must be a builtin string");
112 return;
113 }
114 const char* path = DartUtils::GetStringValue(path_handle);
116 intptr_t args_length = 0;
117 char** string_args =
118 ExtractCStringList(arguments, status_handle,
119 "Arguments must be builtin strings", &args_length);
120 if (string_args == nullptr) {
122 return;
123 }
124 Dart_Handle working_directory_handle = Dart_GetNativeArgument(args, 4);
125 // Defaults to the current working directory.
126 const char* working_directory = nullptr;
127 if (Dart_IsString(working_directory_handle)) {
128 working_directory = DartUtils::GetStringValue(working_directory_handle);
129 } else if (!Dart_IsNull(working_directory_handle)) {
130 result = DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
132 result =
133 DartUtils::SetStringField(status_handle, "_errorMessage",
134 "WorkingDirectory must be a builtin string");
137 return;
138 }
140 intptr_t environment_length = 0;
141 char** string_environment = nullptr;
142 if (!Dart_IsNull(environment)) {
143 string_environment = ExtractCStringList(
144 environment, status_handle,
145 "Environment values must be builtin strings", &environment_length);
146 if (string_environment == nullptr) {
148 return;
149 }
150 }
151 int64_t mode =
153 Dart_Handle stdin_handle = Dart_GetNativeArgument(args, 7);
154 Dart_Handle stdout_handle = Dart_GetNativeArgument(args, 8);
155 Dart_Handle stderr_handle = Dart_GetNativeArgument(args, 9);
156 Dart_Handle exit_handle = Dart_GetNativeArgument(args, 10);
157 intptr_t pid = -1;
158 char* os_error_message = nullptr; // Scope allocated by Process::Start.
159
160 int error_code = Process::Start(
161 namespc, path, string_args, args_length, working_directory,
162 string_environment, environment_length,
163 static_cast<ProcessStartMode>(mode), &process_stdout, &process_stdin,
164 &process_stderr, &pid, &exit_event, &os_error_message);
165 if (error_code == 0) {
166 if (Process::ModeHasStdio(static_cast<ProcessStartMode>(mode))) {
167 Socket::SetSocketIdNativeField(stdin_handle, process_stdin,
169 Socket::SetSocketIdNativeField(stdout_handle, process_stdout,
171 Socket::SetSocketIdNativeField(stderr_handle, process_stderr,
173 }
174 if (Process::ModeIsAttached(static_cast<ProcessStartMode>(mode))) {
175 Socket::SetSocketIdNativeField(exit_handle, exit_event,
177 }
179 } else {
180 result =
181 DartUtils::SetIntegerField(status_handle, "_errorCode", error_code);
183
184 const char* error_message = (os_error_message != nullptr)
185 ? os_error_message
186 : "Failed to get error message";
187 Dart_Handle val = DartUtils::NewString(error_message);
188 if (Dart_IsError(val)) {
189 // Try to clean the message from non-ASCII characters.
190 const intptr_t len = strlen(error_message);
191 char* ascii_message =
192 reinterpret_cast<char*>(Dart_ScopeAllocate(len + 1));
193 for (intptr_t i = 0; i < len; i++) {
194 if (static_cast<uint8_t>(error_message[i]) < 0x80) {
195 ascii_message[i] = error_message[i];
196 } else {
197 ascii_message[i] = '?';
198 }
199 }
200 ascii_message[len] = '\0';
201
203 "Failed to start %s. OS returned an error (code %d) which can't be "
204 "fully converted to Dart string (%s): %s",
205 path, error_code, Dart_GetError(val), ascii_message);
206 }
207 result = Dart_SetField(status_handle, DartUtils::NewString("_errorMessage"),
208 val);
210 }
211 Dart_SetBooleanReturnValue(args, error_code == 0);
212}
213
216 Socket* process_stdin =
218 Socket* process_stdout =
220 Socket* process_stderr =
222 Socket* exit_event =
225 intptr_t pid;
227 bool success = Process::Wait(pid, process_stdin->fd(), process_stdout->fd(),
228 process_stderr->fd(), exit_event->fd(), &result);
229 // Process::Wait() closes the file handles, so blow away the fds in the
230 // Sockets so that they don't get picked up by the finalizer on _NativeSocket.
231 process_stdin->CloseFd();
232 process_stdout->CloseFd();
233 process_stderr->CloseFd();
234 exit_event->CloseFd();
235 if (success) {
236 Dart_Handle out = result.stdout_data();
237 ThrowIfError(out);
238 Dart_Handle err = result.stderr_data();
239 ThrowIfError(err);
240 Dart_Handle list = Dart_NewList(4);
241 Dart_ListSetAt(list, 0, Dart_NewInteger(pid));
242 Dart_ListSetAt(list, 1, Dart_NewInteger(result.exit_code()));
243 Dart_ListSetAt(list, 2, out);
244 Dart_ListSetAt(list, 3, err);
246 } else {
248 Process::Kill(pid, 9);
250 }
251}
252
259
261 int64_t status = 0;
262 // Ignore result if passing invalid argument and just exit 0.
264 Process::RunExitHook(status);
266 // We're not doing a full VM shutdown with Dart_Cleanup, which might block,
267 // and other VM threads may be accessing state with global destructors, so
268 // we skip global destructors by using _exit instead of exit.
269 Platform::_Exit(static_cast<int>(status));
270}
271
273 int64_t status = 0;
274 // Ignore result if passing invalid argument and just set exit code to 0.
277}
278
282
284 ScopedBlockingCall blocker;
285 int64_t milliseconds = 0;
286 // Ignore result if passing invalid argument and just set exit code to 0.
288 TimerUtils::Sleep(milliseconds);
289}
290
292 // Ignore result if passing invalid argument and just set exit code to 0.
293 intptr_t pid = -1;
295 if (Dart_IsNull(process)) {
297 } else {
299 }
301}
302
312
317
322
327
330 intptr_t bytes_length = 0;
331 Dart_Handle result = Dart_ListLength(bytes, &bytes_length);
333 uint8_t* buffer = Dart_ScopeAllocate(bytes_length + 1);
334 result = Dart_ListGetAsBytes(bytes, 0, buffer, bytes_length);
335 buffer[bytes_length] = '\0';
337 intptr_t len;
338 char* str = StringUtils::ConsoleStringToUtf8(reinterpret_cast<char*>(buffer),
339 bytes_length, &len);
340 if (str == nullptr) {
342 "SystemEncodingToString not supported on this operating system"));
343 }
344 result = Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(str), len);
347}
348
351 char* utf8;
352 intptr_t utf8_len;
354 Dart_StringToUTF8(str, reinterpret_cast<uint8_t**>(&utf8), &utf8_len);
356 intptr_t system_len;
357 const char* system_string =
358 StringUtils::Utf8ToConsoleString(utf8, utf8_len, &system_len);
359 if (system_string == nullptr) {
361 "StringToSystemEncoding not supported on this operating system"));
362 }
363 uint8_t* buffer = nullptr;
364 Dart_Handle external_array = IOBuffer::Allocate(system_len, &buffer);
365 if (Dart_IsNull(external_array)) {
367 return;
368 }
369 if (!Dart_IsError(external_array)) {
370 memmove(buffer, system_string, system_len);
371 }
372 Dart_SetReturnValue(args, external_array);
373}
374
376 int64_t current_rss = Process::CurrentRSS();
377 if (current_rss < 0) {
379 return;
380 }
381 Dart_SetIntegerReturnValue(args, current_rss);
382}
383
385 int64_t max_rss = Process::MaxRSS();
386 if (max_rss < 0) {
388 return;
389 }
391}
392
393void Process::GetRSSInformation(int64_t* max_rss, int64_t* current_rss) {
394 ASSERT(max_rss != nullptr);
395 ASSERT(current_rss != nullptr);
396 // Max RSS should be queried after current RSS to produce
397 // consistent values as current RSS can grow beyond max RSS which
398 // was queried before.
399 *current_rss = Process::CurrentRSS();
400 *max_rss = Process::MaxRSS();
401}
402
403} // namespace bin
404} // namespace dart
#define FUNCTION_NAME(name)
Definition builtin.h:19
static int64_t GetInt64ValueCheckRange(Dart_Handle value_obj, int64_t lower, int64_t upper)
Definition dartutils.cc:94
static Dart_Handle NewDartOSError()
Definition dartutils.cc:706
static bool GetInt64Value(Dart_Handle value_obj, int64_t *value)
Definition dartutils.cc:116
static const char * GetStringValue(Dart_Handle str_obj)
Definition dartutils.cc:132
static Dart_Handle NewStringFormatted(const char *format,...)
Definition dartutils.cc:790
static Dart_Handle NewDartUnsupportedError(const char *message)
Definition dartutils.cc:758
static Dart_Handle NewString(const char *str)
Definition dartutils.h:214
static Dart_Handle SetIntegerField(Dart_Handle handle, const char *name, int64_t val)
Definition dartutils.cc:207
static Dart_Handle SetStringField(Dart_Handle handle, const char *name, const char *val)
Definition dartutils.cc:213
static intptr_t GetIntptrValue(Dart_Handle value_obj)
Definition dartutils.cc:104
static Dart_Handle Allocate(intptr_t size, uint8_t **buffer)
Definition io_buffer.cc:12
static Namespace * GetNamespace(Dart_NativeArguments args, intptr_t index)
Definition namespace.cc:101
static DART_NORETURN void _Exit(int exit_code)
static bool ModeIsAttached(ProcessStartMode mode)
Definition process.cc:62
static void ClearSignalHandler(intptr_t signal, Dart_Port port)
static void SetGlobalExitCode(int exit_code)
Definition process.h:129
static bool ModeHasStdio(ProcessStartMode mode)
Definition process.cc:66
static Dart_Handle GetProcessIdNativeField(Dart_Handle process, intptr_t *pid)
Definition process.cc:318
static int64_t CurrentRSS()
static void GetRSSInformation(int64_t *max_rss, int64_t *current_rss)
Definition process.cc:393
static intptr_t CurrentProcessId()
static int GlobalExitCode()
Definition process.h:124
static bool Wait(intptr_t id, intptr_t in, intptr_t out, intptr_t err, intptr_t exit_handler, ProcessResult *result)
static int64_t MaxRSS()
static bool Kill(intptr_t id, int signal)
static intptr_t SetSignalHandler(intptr_t signal)
static Dart_Handle SetProcessIdNativeField(Dart_Handle process, intptr_t pid)
Definition process.cc:323
static void ClearAllSignalHandlers()
Definition process.cc:70
static void RunExitHook(int64_t exit_code)
Definition process.h:136
static int Start(Namespace *namespc, const char *path, char *arguments[], intptr_t arguments_length, const char *working_directory, char *environment[], intptr_t environment_length, ProcessStartMode mode, intptr_t *in, intptr_t *out, intptr_t *err, intptr_t *id, intptr_t *exit_handler, char **os_error_message)
intptr_t fd() const
Definition socket.h:52
static void SetSocketIdNativeField(Dart_Handle handle, intptr_t id, SocketFinalizer finalizer)
Definition socket.cc:1489
static Socket * GetSocketIdNativeField(Dart_Handle socket)
Definition socket.cc:1496
static const char * Utf8ToConsoleString(const char *utf8, intptr_t len=-1, intptr_t *result_len=nullptr)
static const char * ConsoleStringToUtf8(const char *str, intptr_t len=-1, intptr_t *result_len=nullptr)
static void Sleep(int64_t millis)
#define ILLEGAL_PORT
Definition dart_api.h:1530
struct _Dart_Handle * Dart_Handle
Definition dart_api.h:258
struct _Dart_NativeArguments * Dart_NativeArguments
Definition dart_api.h:3010
#define ASSERT(E)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
static const uint8_t buffer[]
const uint8_t uint32_t uint32_t GError ** error
GAsyncResult * result
size_t length
void FUNCTION_NAME() Process_SetExitCode(Dart_NativeArguments args)
Definition process.cc:272
void FUNCTION_NAME() Process_Pid(Dart_NativeArguments args)
Definition process.cc:291
static Dart_Handle ThrowIfError(Dart_Handle handle)
Definition dartutils.h:31
void FUNCTION_NAME() ProcessInfo_CurrentRSS(Dart_NativeArguments args)
Definition process.cc:375
static char ** ExtractCStringList(Dart_Handle strings, Dart_Handle status_handle, const char *error_msg, intptr_t *length)
Definition process.cc:23
void FUNCTION_NAME() Process_GetExitCode(Dart_NativeArguments args)
Definition process.cc:279
void FUNCTION_NAME() Process_Start(Dart_NativeArguments args)
Definition process.cc:76
void FUNCTION_NAME() Process_Sleep(Dart_NativeArguments args)
Definition process.cc:283
static constexpr int kProcessIdNativeField
Definition process.cc:20
void FUNCTION_NAME() Process_Wait(Dart_NativeArguments args)
Definition process.cc:214
void FUNCTION_NAME() ProcessInfo_MaxRSS(Dart_NativeArguments args)
Definition process.cc:384
void FUNCTION_NAME() Process_SetSignalHandler(Dart_NativeArguments args)
Definition process.cc:303
ProcessStartMode
Definition process.h:81
@ kInheritStdio
Definition process.h:83
@ kNormal
Definition process.h:82
@ kDetachedWithStdio
Definition process.h:85
void FUNCTION_NAME() Process_KillPid(Dart_NativeArguments args)
Definition process.cc:253
void FUNCTION_NAME() SystemEncodingToString(Dart_NativeArguments args)
Definition process.cc:328
void FUNCTION_NAME() StringToSystemEncoding(Dart_NativeArguments args)
Definition process.cc:349
@ kLastSignal
Definition process.h:77
void FUNCTION_NAME() Process_Exit(Dart_NativeArguments args)
Definition process.cc:260
void FUNCTION_NAME() Process_ClearSignalHandler(Dart_NativeArguments args)
Definition process.cc:313
static dart::SimpleHashMap * environment
DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str, uint8_t **utf8_array, intptr_t *length)
DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index)
DART_EXPORT Dart_Port Dart_GetMainPortId()
DART_EXPORT Dart_Handle Dart_GetNativeInstanceField(Dart_Handle obj, int index, intptr_t *value)
DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args, bool retval)
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value)
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t *utf8_array, intptr_t length)
DART_EXPORT const char * Dart_GetError(Dart_Handle handle)
DART_EXPORT uint8_t * Dart_ScopeAllocate(intptr_t size)
DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args, Dart_Handle retval)
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list, intptr_t index, Dart_Handle value)
DART_EXPORT bool Dart_IsError(Dart_Handle handle)
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj, int index, intptr_t value)
DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args, int64_t retval)
DART_EXPORT Dart_Handle Dart_GetNativeArgument(Dart_NativeArguments args, int index)
DART_EXPORT void Dart_ExitIsolate()
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container, Dart_Handle name, Dart_Handle value)
DART_EXPORT Dart_Handle Dart_ListGetAsBytes(Dart_Handle list, intptr_t offset, uint8_t *native_array, intptr_t length)
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t *len)
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length)
DART_EXPORT bool Dart_IsList(Dart_Handle object)
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
DART_EXPORT bool Dart_IsNull(Dart_Handle object)
DART_EXPORT bool Dart_IsString(Dart_Handle object)
static void process(const char *inPath, const char *lexer, const char *token, const char *hPath, const char *cppPath)
Definition Main.cpp:114