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

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: Nicer API and Android+Mac versions. 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
« no previous file with comments | « runtime/bin/process_patch.dart ('k') | runtime/bin/signal_blocker.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 static SignalInfo* signal_handlers = NULL;
861 static Mutex* signal_mutex = new Mutex();
862
863
864 SignalInfo::~SignalInfo() {
865 reinterpret_cast<FileHandle*>(fd_)->Close();
866 }
867
868
869 BOOL WINAPI SignalHandler(DWORD signal) {
870 MutexLocker lock(signal_mutex);
871 const SignalInfo* handler = signal_handlers;
872 bool handled = false;
873 while (handler != NULL) {
874 if (handler->signal() == signal) {
875 int value = 0;
876 Socket::Write(handler->fd(), &value, 1);
877 handled = true;
878 }
879 handler = handler->next();
880 }
881 return handled;
882 }
883
884
885 intptr_t GetWinSignal(intptr_t signal) {
886 switch (signal) {
887 case 1: // SIGHUP
888 return CTRL_CLOSE_EVENT;
889 case 2: // SIGINT
890 return CTRL_C_EVENT;
891 default:
892 return -1;
893 }
894 }
895
896
897 intptr_t Process::SetSignalHandler(intptr_t signal) {
898 signal = GetWinSignal(signal);
899 if (signal == -1) return -1;
900
901 // Generate a unique pipe name for the named pipe.
902 static const int kMaxPipeNameSize = 80;
903 wchar_t pipe_name[kMaxPipeNameSize];
904 GenerateNames(1, &pipe_name, kMaxPipeNameSize);
905 if (status != 0) return status;
906
907 HANDLE fds[2];
908 if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) {
909 int error_code = GetLastError();
910 CloseProcessPipe(fds);
911 SetLastError(error_code);
912 return -1;
913 }
914 MutexLocker lock(signal_mutex);
915 FileHandle* write_handle = new FileHandle(fds[kWriteHandle]);
916 write_handle->EnsureInitialized(EventHandler::delegate());
917 intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle);
918 if (signal_handlers == NULL) {
919 if (SetConsoleCtrlHandler(SignalHandler, true) == 0) {
920 int error_code = GetLastError();
921 delete write_handle;
922 CloseProcessPipe(fds);
923 SetLastError(error_code);
924 return -1;
925 }
926 signal_handlers = new SignalInfo(write_fd, signal);
927 } else {
928 new SignalInfo(write_fd, signal, signal_handlers);
929 }
930 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle]));
931 }
932
933
934 void Process::ClearSignalHandler(intptr_t signal) {
935 signal = GetWinSignal(signal);
936 if (signal == -1) return;
937 MutexLocker lock(signal_mutex);
938 SignalInfo* handler = signal_handlers;
939 while (handler != NULL) {
940 if (handler->port() == Dart_GetMainPortId() &&
941 handler->signal() == signal) {
942 handler->Unlink();
943 break;
944 }
945 handler = handler->next();
946 }
947 if (handler != NULL) {
948 if (signal_handlers == handler) {
949 signal_handlers = handler->next();
950 }
951 if (signal_handlers == NULL) {
952 USE(SetConsoleCtrlHandler(SignalHandler, false));
953 }
954 }
955 delete handler;
956 }
957
852 } // namespace bin 958 } // namespace bin
853 } // namespace dart 959 } // namespace dart
854 960
855 #endif // defined(TARGET_OS_WINDOWS) 961 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/bin/process_patch.dart ('k') | runtime/bin/signal_blocker.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698