Files
sdk/runtime/bin/process.cc
T
ager@google.com 6d0f985432 Add exitCode setter to set the exit code returned by the Dart VM
standalone binary on normal termination.

This is needed to be able to set the exit code without cutting
off pending asynchronous operations.

R=sgjesse@google.com,rnystrom@google.com
BUG=

Review URL: https://codereview.chromium.org//11665004

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@16435 260f80e4-7a28-3924-810f-c04153c831b5
2012-12-21 10:36:52 +00:00

239 lines
8.5 KiB
C++

// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "bin/dartutils.h"
#include "bin/io_buffer.h"
#include "bin/process.h"
#include "bin/socket.h"
#include "include/dart_api.h"
static const int kProcessIdNativeField = 0;
int Process::global_exit_code_ = 0;
dart::Mutex Process::global_exit_code_mutex_;
// Extract an array of C strings from a list of Dart strings.
static char** ExtractCStringList(Dart_Handle strings,
Dart_Handle status_handle,
const char* error_msg,
intptr_t* length) {
static const intptr_t kMaxArgumentListLength = 1024 * 1024;
ASSERT(Dart_IsList(strings));
intptr_t len = 0;
Dart_Handle result = Dart_ListLength(strings, &len);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
// Protect against user-defined list implementations that can have
// arbitrary length.
if (len < 0 || len > kMaxArgumentListLength) {
DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
DartUtils::SetStringField(
status_handle, "_errorMessage", "Max argument list length exceeded");
return NULL;
}
*length = len;
char** string_args = new char*[len];
for (int i = 0; i < len; i++) {
Dart_Handle arg = Dart_ListGetAt(strings, i);
if (Dart_IsError(arg)) {
delete[] string_args;
Dart_PropagateError(arg);
}
if (!Dart_IsString(arg)) {
DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
DartUtils::SetStringField(
status_handle, "_errorMessage", error_msg);
delete[] string_args;
return NULL;
}
string_args[i] = const_cast<char *>(DartUtils::GetStringValue(arg));
}
return string_args;
}
void FUNCTION_NAME(Process_Start)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle process = Dart_GetNativeArgument(args, 0);
intptr_t in;
intptr_t out;
intptr_t err;
intptr_t exit_event;
Dart_Handle status_handle = Dart_GetNativeArgument(args, 9);
Dart_Handle path_handle = Dart_GetNativeArgument(args, 1);
// The Dart code verifies that the path implements the String
// interface. However, only builtin Strings are handled by
// GetStringValue.
if (!Dart_IsString(path_handle)) {
DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
DartUtils::SetStringField(
status_handle, "_errorMessage", "Path must be a builtin string");
Dart_SetReturnValue(args, Dart_NewBoolean(false));
Dart_ExitScope();
return;
}
const char* path = DartUtils::GetStringValue(path_handle);
Dart_Handle arguments = Dart_GetNativeArgument(args, 2);
intptr_t args_length = 0;
char** string_args =
ExtractCStringList(arguments,
status_handle,
"Arguments must be builtin strings",
&args_length);
if (string_args == NULL) {
Dart_SetReturnValue(args, Dart_NewBoolean(false));
Dart_ExitScope();
return;
}
Dart_Handle working_directory_handle = Dart_GetNativeArgument(args, 3);
// Defaults to the current working directoy.
const char* working_directory = NULL;
if (Dart_IsString(working_directory_handle)) {
working_directory = DartUtils::GetStringValue(working_directory_handle);
} else if (!Dart_IsNull(working_directory_handle)) {
delete[] string_args;
DartUtils::SetIntegerField(status_handle, "_errorCode", 0);
DartUtils::SetStringField(
status_handle, "_errorMessage",
"WorkingDirectory must be a builtin string");
Dart_SetReturnValue(args, Dart_NewBoolean(false));
Dart_ExitScope();
return;
}
Dart_Handle environment = Dart_GetNativeArgument(args, 4);
intptr_t environment_length = 0;
char** string_environment = NULL;
if (!Dart_IsNull(environment)) {
string_environment =
ExtractCStringList(environment,
status_handle,
"Environment values must be builtin strings",
&environment_length);
if (string_environment == NULL) {
delete[] string_args;
Dart_SetReturnValue(args, Dart_NewBoolean(false));
Dart_ExitScope();
return;
}
}
Dart_Handle in_handle = Dart_GetNativeArgument(args, 5);
Dart_Handle out_handle = Dart_GetNativeArgument(args, 6);
Dart_Handle err_handle = Dart_GetNativeArgument(args, 7);
Dart_Handle exit_handle = Dart_GetNativeArgument(args, 8);
intptr_t pid = -1;
char* os_error_message = NULL;
int error_code = Process::Start(path,
string_args,
args_length,
working_directory,
string_environment,
environment_length,
&in,
&out,
&err,
&pid,
&exit_event,
&os_error_message);
if (error_code == 0) {
Socket::SetSocketIdNativeField(in_handle, in);
Socket::SetSocketIdNativeField(out_handle, out);
Socket::SetSocketIdNativeField(err_handle, err);
Socket::SetSocketIdNativeField(exit_handle, exit_event);
Process::SetProcessIdNativeField(process, pid);
} else {
DartUtils::SetIntegerField(
status_handle, "_errorCode", error_code);
DartUtils::SetStringField(
status_handle, "_errorMessage", os_error_message);
}
delete[] string_args;
delete[] string_environment;
free(os_error_message);
Dart_SetReturnValue(args, Dart_NewBoolean(error_code == 0));
Dart_ExitScope();
}
void FUNCTION_NAME(Process_Kill)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle process = Dart_GetNativeArgument(args, 1);
intptr_t pid = -1;
Process::GetProcessIdNativeField(process, &pid);
int signal = DartUtils::GetIntegerValue(Dart_GetNativeArgument(args, 2));
bool success = Process::Kill(pid, signal);
Dart_SetReturnValue(args, Dart_NewBoolean(success));
Dart_ExitScope();
}
void FUNCTION_NAME(Process_Exit)(Dart_NativeArguments args) {
Dart_EnterScope();
int64_t status = 0;
// Ignore result if passing invalid argument and just exit 0.
DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
Dart_ExitScope();
exit(static_cast<int>(status));
}
void FUNCTION_NAME(Process_SetExitCode)(Dart_NativeArguments args) {
Dart_EnterScope();
int64_t status = 0;
// Ignore result if passing invalid argument and just set exit code to 0.
DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
Process::SetGlobalExitCode(status);
Dart_ExitScope();
}
Dart_Handle Process::GetProcessIdNativeField(Dart_Handle process,
intptr_t* pid) {
return Dart_GetNativeInstanceField(process, kProcessIdNativeField, pid);
}
Dart_Handle Process::SetProcessIdNativeField(Dart_Handle process,
intptr_t pid) {
return Dart_SetNativeInstanceField(process, kProcessIdNativeField, pid);
}
void FUNCTION_NAME(SystemEncodingToString)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle bytes = Dart_GetNativeArgument(args, 0);
intptr_t bytes_length = 0;
Dart_Handle result = Dart_ListLength(bytes, &bytes_length);
if (Dart_IsError(result)) Dart_PropagateError(result);
uint8_t* buffer = new uint8_t[bytes_length + 1];
result = Dart_ListGetAsBytes(bytes, 0, buffer, bytes_length);
buffer[bytes_length] = '\0';
if (Dart_IsError(result)) {
delete[] buffer;
Dart_PropagateError(result);
}
char* str =
StringUtils::ConsoleStringToUtf8(reinterpret_cast<char*>(buffer));
Dart_SetReturnValue(args, DartUtils::NewString(str));
if (str != reinterpret_cast<char*>(buffer)) free(str);
Dart_ExitScope();
}
void FUNCTION_NAME(StringToSystemEncoding)(Dart_NativeArguments args) {
Dart_EnterScope();
Dart_Handle str = Dart_GetNativeArgument(args, 0);
const char* utf8 = DartUtils::GetStringValue(str);
const char* system_string = StringUtils::Utf8ToConsoleString(utf8);
int external_length = strlen(system_string);
uint8_t* buffer = NULL;
Dart_Handle external_array = IOBuffer::Allocate(external_length, &buffer);
memmove(buffer, system_string, external_length);
if (utf8 != system_string) free(const_cast<char*>(system_string));
Dart_SetReturnValue(args, external_array);
Dart_ExitScope();
}