Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: runtime/bin/process_win.cc

Issue 108003009: Signal handling. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Clean up impl and add test. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_WINDOWS) 6 #if defined(TARGET_OS_WINDOWS)
7 7
8 #include <process.h> // NOLINT 8 #include <process.h> // NOLINT
9 9
10 #include "bin/builtin.h" 10 #include "bin/builtin.h"
11 #include "bin/process.h" 11 #include "bin/process.h"
12 #include "bin/eventhandler.h" 12 #include "bin/eventhandler.h"
13 #include "bin/log.h" 13 #include "bin/log.h"
14 #include "bin/socket.h"
14 #include "bin/thread.h" 15 #include "bin/thread.h"
15 #include "bin/utils.h" 16 #include "bin/utils.h"
16 #include "bin/utils_win.h" 17 #include "bin/utils_win.h"
17 18
18 19
19 namespace dart { 20 namespace dart {
20 namespace bin { 21 namespace bin {
21 22
22 static const int kReadHandle = 0; 23 static const int kReadHandle = 0;
23 static const int kWriteHandle = 1; 24 static const int kWriteHandle = 1;
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); 343 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute"));
343 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( 344 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>(
344 reinterpret_cast<DeleteProcThreadAttrListFn>( 345 reinterpret_cast<DeleteProcThreadAttrListFn>(
345 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList"))); 346 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")));
346 load_attempted = true; 347 load_attempted = true;
347 return delete_proc_thread_attr_list != NULL; 348 return delete_proc_thread_attr_list != NULL;
348 } 349 }
349 return delete_proc_thread_attr_list != NULL; 350 return delete_proc_thread_attr_list != NULL;
350 } 351 }
351 352
352 353 int GenerateNames(int count, wchar_t* pipe_names[], int max_length) {
353 int Process::Start(const char* path,
354 char* arguments[],
355 intptr_t arguments_length,
356 const char* working_directory,
357 char* environment[],
358 intptr_t environment_length,
359 intptr_t* in,
360 intptr_t* out,
361 intptr_t* err,
362 intptr_t* id,
363 intptr_t* exit_handler,
364 char** os_error_message) {
365 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
366 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
367 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
368 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
369
370 // Generate unique pipe names for the four named pipes needed.
371 static const int kMaxPipeNameSize = 80;
372 wchar_t pipe_names[4][kMaxPipeNameSize];
373 UUID uuid; 354 UUID uuid;
374 RPC_STATUS status = UuidCreateSequential(&uuid); 355 RPC_STATUS status = UuidCreateSequential(&uuid);
375 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { 356 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
376 SetOsErrorMessage(os_error_message); 357 SetOsErrorMessage(os_error_message);
377 Log::PrintErr("UuidCreateSequential failed %d\n", status); 358 Log::PrintErr("UuidCreateSequential failed %d\n", status);
378 return status; 359 return status;
379 } 360 }
380 RPC_WSTR uuid_string; 361 RPC_WSTR uuid_string;
381 status = UuidToStringW(&uuid, &uuid_string); 362 status = UuidToStringW(&uuid, &uuid_string);
382 if (status != RPC_S_OK) { 363 if (status != RPC_S_OK) {
383 SetOsErrorMessage(os_error_message); 364 SetOsErrorMessage(os_error_message);
384 Log::PrintErr("UuidToString failed %d\n", status); 365 Log::PrintErr("UuidToString failed %d\n", status);
385 return status; 366 return status;
386 } 367 }
387 for (int i = 0; i < 4; i++) { 368 for (int i = 0; i < count; i++) {
388 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; 369 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart";
389 _snwprintf(pipe_names[i], 370 _snwprintf(pipe_names[i],
390 kMaxPipeNameSize, 371 max_length,
391 L"%s_%s_%d", prefix, uuid_string, i + 1); 372 L"%s_%s_%d", prefix, uuid_string, i + 1);
392 } 373 }
393 status = RpcStringFreeW(&uuid_string); 374 status = RpcStringFreeW(&uuid_string);
394 if (status != RPC_S_OK) { 375 if (status != RPC_S_OK) {
395 SetOsErrorMessage(os_error_message); 376 SetOsErrorMessage(os_error_message);
396 Log::PrintErr("RpcStringFree failed %d\n", status); 377 Log::PrintErr("RpcStringFree failed %d\n", status);
397 return status; 378 return status;
398 } 379 }
380 return 0;
381 }
382
383
384 int Process::Start(const char* path,
385 char* arguments[],
386 intptr_t arguments_length,
387 const char* working_directory,
388 char* environment[],
389 intptr_t environment_length,
390 intptr_t* in,
391 intptr_t* out,
392 intptr_t* err,
393 intptr_t* id,
394 intptr_t* exit_handler,
395 char** os_error_message) {
396 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
397 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
398 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
399 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE };
400
401 // Generate unique pipe names for the four named pipes needed.
402 static const int kMaxPipeNameSize = 80;
403 wchar_t pipe_names[4][kMaxPipeNameSize];
404 int status = GenerateNames(4, pipe_names, kMaxPipeNameSize);
405 if (status != 0) return status;
399 406
400 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) { 407 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
401 int error_code = SetOsErrorMessage(os_error_message); 408 int error_code = SetOsErrorMessage(os_error_message);
402 CloseProcessPipes( 409 CloseProcessPipes(
403 stdin_handles, stdout_handles, stderr_handles, exit_handles); 410 stdin_handles, stdout_handles, stderr_handles, exit_handles);
404 return error_code; 411 return error_code;
405 } 412 }
406 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) { 413 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
407 int error_code = SetOsErrorMessage(os_error_message); 414 int error_code = SetOsErrorMessage(os_error_message);
408 CloseProcessPipes( 415 CloseProcessPipes(
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 849
843 void Process::TerminateExitCodeHandler() { 850 void Process::TerminateExitCodeHandler() {
844 // Nothing needs to be done on Windows. 851 // Nothing needs to be done on Windows.
845 } 852 }
846 853
847 854
848 intptr_t Process::CurrentProcessId() { 855 intptr_t Process::CurrentProcessId() {
849 return static_cast<intptr_t>(GetCurrentProcessId()); 856 return static_cast<intptr_t>(GetCurrentProcessId());
850 } 857 }
851 858
859
860 class SignalInfo {
861 public:
862 SignalInfo(intptr_t fd, int signal, SignalInfo* prev = NULL)
863 : fd_(fd),
864 signal_(signal),
865 port_(Dart_GetMainPortId()),
866 next_(NULL),
867 prev_(prev) {
868 if (prev_ != NULL) {
869 prev_->next_ = this;
870 }
871 }
872
873 ~SignalInfo() {
874 reinterpret_cast<FileHandle*>(fd_)->Close();
875 }
876
877 void Unlink() {
878 if (prev_ != NULL) {
879 prev_->next_ = next_;
880 }
881 if (next_ != NULL) {
882 next_->prev_ = prev_;
883 }
884 }
885
886 intptr_t fd() const { return fd_; }
887 int signal() const { return signal_; }
888 Dart_Port port() const { return port_; }
889 SignalInfo* next() const { return next_; }
890
891 private:
892 intptr_t fd_;
893 int signal_;
894 Dart_Port port_;
895 SignalInfo* next_;
896 SignalInfo* prev_;
897 };
898
899
900 static SignalInfo* signal_handlers = NULL;
901 static Mutex* signal_mutex = new Mutex();
902
903
904 BOOL WINAPI SignalHandler(DWORD signal) {
905 MutexLocker lock(signal_mutex);
906 const SignalInfo* handler = signal_handlers;
907 bool handled = false;
908 while (handler != NULL) {
909 if (handler->signal() == signal) {
910 int value = 0;
911 Socket::Write(handler->fd(), &value, 1);
912 handled = true;
913 }
914 handler = handler->next();
915 }
916 return handled;
917 }
918
919
920 intptr_t GetWinSignal(intptr_t signal) {
921 switch (signal) {
922 case 1: // SIGHUP
923 return CTRL_CLOSE_EVENT;
924 case 2: // SIGINT
925 return CTRL_C_EVENT;
926 default:
927 return -1;
928 }
929 }
930
931
932 intptr_t Process::SetSignalHandler(intptr_t signal) {
933 signal = GetWinSignal(signal);
934 if (signal == -1) return -1;
935
936 // Generate a unique pipe name for the named pipe.
937 static const int kMaxPipeNameSize = 80;
938 wchar_t pipe_name[kMaxPipeNameSize];
939 GenerateNames(1, &pipe_name, kMaxPipeNameSize);
940 if (status != 0) return status;
941
942 HANDLE fds[2];
943 if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) {
944 int error_code = GetLastError();
945 CloseProcessPipe(fds);
946 SetLastError(error_code);
947 return -1;
948 }
949 MutexLocker lock(signal_mutex);
950 FileHandle* write_handle = new FileHandle(fds[kWriteHandle]);
951 write_handle->EnsureInitialized(EventHandler::delegate());
952 intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle);
953 if (signal_handlers == NULL) {
954 if (SetConsoleCtrlHandler(SignalHandler, true) == 0) {
955 int error_code = GetLastError();
956 delete write_handle;
957 CloseProcessPipe(fds);
958 SetLastError(error_code);
959 return -1;
960 }
961 signal_handlers = new SignalInfo(write_fd, signal);
962 } else {
963 new SignalInfo(write_fd, signal, signal_handlers);
964 }
965 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle]));
966 }
967
968
969 void Process::ClearSignalHandler(intptr_t signal) {
970 signal = GetWinSignal(signal);
971 if (signal == -1) return;
972 MutexLocker lock(signal_mutex);
973 SignalInfo* handler = signal_handlers;
974 while (handler != NULL) {
975 if (handler->port() == Dart_GetMainPortId() &&
976 handler->signal() == signal) {
977 handler->Unlink();
978 break;
979 }
980 handler = handler->next();
981 }
982 if (handler != NULL) {
983 if (signal_handlers == handler) {
984 signal_handlers = handler->next();
985 }
986 if (signal_handlers == NULL) {
987 USE(SetConsoleCtrlHandler(SignalHandler, false));
988 }
989 }
990 delete handler;
991 }
992
852 } // namespace bin 993 } // namespace bin
853 } // namespace dart 994 } // namespace dart
854 995
855 #endif // defined(TARGET_OS_WINDOWS) 996 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698