Index: runtime/bin/process_win.cc |
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc |
index 00514c775a60d437ea6a69daae7ce44ada2dab59..3875b4f51f1faef3ffd49cdd6fe2dd70853e9a21 100644 |
--- a/runtime/bin/process_win.cc |
+++ b/runtime/bin/process_win.cc |
@@ -11,6 +11,7 @@ |
#include "bin/process.h" |
#include "bin/eventhandler.h" |
#include "bin/log.h" |
+#include "bin/socket.h" |
#include "bin/thread.h" |
#include "bin/utils.h" |
#include "bin/utils_win.h" |
@@ -350,6 +351,33 @@ static bool EnsureInitialized() { |
} |
+const int kMaxPipeNameSize = 80; |
+template<int Count> |
+static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { |
+ UUID uuid; |
+ RPC_STATUS status = UuidCreateSequential(&uuid); |
+ if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
+ return status; |
+ } |
+ RPC_WSTR uuid_string; |
+ status = UuidToStringW(&uuid, &uuid_string); |
+ if (status != RPC_S_OK) { |
+ return status; |
+ } |
+ for (int i = 0; i < Count; i++) { |
+ static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
+ _snwprintf(pipe_names[i], |
+ kMaxPipeNameSize, |
+ L"%s_%s_%d", prefix, uuid_string, i + 1); |
+ } |
+ status = RpcStringFreeW(&uuid_string); |
+ if (status != RPC_S_OK) { |
+ return status; |
+ } |
+ return 0; |
+} |
+ |
+ |
int Process::Start(const char* path, |
char* arguments[], |
intptr_t arguments_length, |
@@ -368,34 +396,13 @@ int Process::Start(const char* path, |
HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
// Generate unique pipe names for the four named pipes needed. |
- static const int kMaxPipeNameSize = 80; |
wchar_t pipe_names[4][kMaxPipeNameSize]; |
- UUID uuid; |
- RPC_STATUS status = UuidCreateSequential(&uuid); |
- if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
+ int status = GenerateNames<4>(pipe_names); |
+ if (status != 0) { |
SetOsErrorMessage(os_error_message); |
Log::PrintErr("UuidCreateSequential failed %d\n", status); |
return status; |
} |
- RPC_WSTR uuid_string; |
- status = UuidToStringW(&uuid, &uuid_string); |
- if (status != RPC_S_OK) { |
- SetOsErrorMessage(os_error_message); |
- Log::PrintErr("UuidToString failed %d\n", status); |
- return status; |
- } |
- for (int i = 0; i < 4; i++) { |
- static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
- _snwprintf(pipe_names[i], |
- kMaxPipeNameSize, |
- L"%s_%s_%d", prefix, uuid_string, i + 1); |
- } |
- status = RpcStringFreeW(&uuid_string); |
- if (status != RPC_S_OK) { |
- SetOsErrorMessage(os_error_message); |
- Log::PrintErr("RpcStringFree failed %d\n", status); |
- return status; |
- } |
if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) { |
int error_code = SetOsErrorMessage(os_error_message); |
@@ -849,6 +856,102 @@ intptr_t Process::CurrentProcessId() { |
return static_cast<intptr_t>(GetCurrentProcessId()); |
} |
+ |
+static SignalInfo* signal_handlers = NULL; |
+static Mutex* signal_mutex = new Mutex(); |
+ |
+ |
+SignalInfo::~SignalInfo() { |
+ reinterpret_cast<FileHandle*>(fd_)->Close(); |
+} |
+ |
+ |
+BOOL WINAPI SignalHandler(DWORD signal) { |
+ MutexLocker lock(signal_mutex); |
+ const SignalInfo* handler = signal_handlers; |
+ bool handled = false; |
+ while (handler != NULL) { |
+ if (handler->signal() == signal) { |
+ int value = 0; |
+ Socket::Write(handler->fd(), &value, 1); |
+ handled = true; |
+ } |
+ handler = handler->next(); |
+ } |
+ return handled; |
+} |
+ |
+ |
+intptr_t GetWinSignal(intptr_t signal) { |
+ switch (signal) { |
+ case kSighup: return CTRL_CLOSE_EVENT; |
+ case kSigint: return CTRL_C_EVENT; |
+ default: |
+ return -1; |
+ } |
+} |
+ |
+ |
+intptr_t Process::SetSignalHandler(intptr_t signal) { |
+ signal = GetWinSignal(signal); |
+ if (signal == -1) return -1; |
+ |
+ // Generate a unique pipe name for the named pipe. |
+ wchar_t pipe_name[kMaxPipeNameSize]; |
+ int status = GenerateNames<1>(&pipe_name); |
+ if (status != 0) return status; |
+ |
+ HANDLE fds[2]; |
+ if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) { |
+ int error_code = GetLastError(); |
+ CloseProcessPipe(fds); |
+ SetLastError(error_code); |
+ return -1; |
+ } |
+ MutexLocker lock(signal_mutex); |
+ FileHandle* write_handle = new FileHandle(fds[kWriteHandle]); |
+ write_handle->EnsureInitialized(EventHandler::delegate()); |
+ intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle); |
+ if (signal_handlers == NULL) { |
+ if (SetConsoleCtrlHandler(SignalHandler, true) == 0) { |
+ int error_code = GetLastError(); |
+ delete write_handle; |
+ CloseProcessPipe(fds); |
+ SetLastError(error_code); |
+ return -1; |
+ } |
+ signal_handlers = new SignalInfo(write_fd, signal); |
+ } else { |
+ new SignalInfo(write_fd, signal, signal_handlers); |
+ } |
+ return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); |
+} |
+ |
+ |
+void Process::ClearSignalHandler(intptr_t signal) { |
+ signal = GetWinSignal(signal); |
+ if (signal == -1) return; |
+ MutexLocker lock(signal_mutex); |
+ SignalInfo* handler = signal_handlers; |
+ while (handler != NULL) { |
+ if (handler->port() == Dart_GetMainPortId() && |
+ handler->signal() == signal) { |
+ handler->Unlink(); |
+ break; |
+ } |
+ handler = handler->next(); |
+ } |
+ if (handler != NULL) { |
+ if (signal_handlers == handler) { |
+ signal_handlers = handler->next(); |
+ } |
+ if (signal_handlers == NULL) { |
+ USE(SetConsoleCtrlHandler(SignalHandler, false)); |
+ } |
+ } |
+ delete handler; |
+} |
+ |
} // namespace bin |
} // namespace dart |