Chromium Code Reviews| 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 |