Index: runtime/bin/process_win.cc |
diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc |
index 00514c775a60d437ea6a69daae7ce44ada2dab59..8c539bd7d035fafb60a6013522bdfe1fd33cbc86 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" |
@@ -849,6 +850,163 @@ intptr_t Process::CurrentProcessId() { |
return static_cast<intptr_t>(GetCurrentProcessId()); |
} |
+ |
+class SignalInfo { |
+ public: |
+ SignalInfo(intptr_t fd, int signal, SignalInfo* prev = NULL) |
+ : fd_(fd), |
+ signal_(signal), |
+ port_(Dart_GetMainPortId()), |
+ next_(NULL), |
+ prev_(prev) { |
+ if (prev_ != NULL) { |
+ prev_->next_ = this; |
+ } |
+ } |
+ |
+ ~SignalInfo() { |
+ reinterpret_cast<FileHandle*>(fd_)->Close(); |
+ } |
+ |
+ void Unlink() { |
+ if (prev_ != NULL) { |
+ prev_->next_ = next_; |
+ } |
+ if (next_ != NULL) { |
+ next_->prev_ = prev_; |
+ } |
+ } |
+ |
+ intptr_t fd() const { return fd_; } |
+ int signal() const { return signal_; } |
+ Dart_Port port() const { return port_; } |
+ SignalInfo* next() const { return next_; } |
+ |
+ private: |
+ intptr_t fd_; |
+ int signal_; |
+ Dart_Port port_; |
+ SignalInfo* next_; |
+ SignalInfo* prev_; |
+}; |
+ |
+ |
+static SignalInfo* signal_handlers = NULL; |
+static Mutex* signal_mutex = new Mutex(); |
+ |
+ |
+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 1: // SIGHUP |
+ return CTRL_CLOSE_EVENT; |
+ case 2: // SIGINT |
+ return CTRL_C_EVENT; |
+ default: |
+ return -1; |
+ } |
+} |
+ |
+ |
+intptr_t Process::SetSignalHandler(intptr_t signal) { |
+ signal = GetWinSignal(signal); |
+ if (signal == -1) return -1; |
Søren Gjesse
2013/12/18 08:07:14
Throw here?
Dart_ThrowException(DartUtils::NewDar
Anders Johnsen
2013/12/18 21:20:29
Returning -1 will throw as well (in process.cc). W
|
+ // Generate a unique pipe name for the named pipe. |
Søren Gjesse
2013/12/18 08:07:14
Please factor out this named pipe name generation
Anders Johnsen
2013/12/18 21:20:29
Done.
|
+ static const int kMaxPipeNameSize = 80; |
+ wchar_t pipe_name[kMaxPipeNameSize]; |
+ UUID uuid; |
+ RPC_STATUS status = UuidCreateSequential(&uuid); |
+ if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { |
+ int error_code = GetLastError(); |
+ Log::PrintErr("UuidCreateSequential failed %d\n", status); |
+ SetLastError(error_code); |
+ return -1; |
+ } |
+ RPC_WSTR uuid_string; |
+ status = UuidToStringW(&uuid, &uuid_string); |
+ if (status != RPC_S_OK) { |
+ int error_code = GetLastError(); |
+ Log::PrintErr("UuidToString failed %d\n", status); |
+ SetLastError(error_code); |
+ return -1; |
+ } |
+ static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
+ _snwprintf(pipe_name, |
+ kMaxPipeNameSize, |
+ L"%s_%s", prefix, uuid_string); |
+ status = RpcStringFreeW(&uuid_string); |
+ if (status != RPC_S_OK) { |
+ int error_code = GetLastError(); |
+ Log::PrintErr("RpcStringFree failed %d\n", status); |
+ SetLastError(error_code); |
+ return -1; |
+ } |
+ 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 |