| OLD | NEW |
| 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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
| 6 | 6 |
| 7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
| 8 #if defined(TARGET_OS_WINDOWS) | 8 #if defined(TARGET_OS_WINDOWS) |
| 9 | 9 |
| 10 #include "bin/process.h" | 10 #include "bin/process.h" |
| (...skipping 27 matching lines...) Expand all Loading... |
| 38 // ProcessInfoList. | 38 // ProcessInfoList. |
| 39 class ProcessInfo { | 39 class ProcessInfo { |
| 40 public: | 40 public: |
| 41 ProcessInfo(DWORD process_id, | 41 ProcessInfo(DWORD process_id, |
| 42 HANDLE process_handle, | 42 HANDLE process_handle, |
| 43 HANDLE wait_handle, | 43 HANDLE wait_handle, |
| 44 HANDLE exit_pipe) | 44 HANDLE exit_pipe) |
| 45 : process_id_(process_id), | 45 : process_id_(process_id), |
| 46 process_handle_(process_handle), | 46 process_handle_(process_handle), |
| 47 wait_handle_(wait_handle), | 47 wait_handle_(wait_handle), |
| 48 exit_pipe_(exit_pipe) { } | 48 exit_pipe_(exit_pipe) {} |
| 49 | 49 |
| 50 ~ProcessInfo() { | 50 ~ProcessInfo() { |
| 51 BOOL success = CloseHandle(process_handle_); | 51 BOOL success = CloseHandle(process_handle_); |
| 52 if (!success) { | 52 if (!success) { |
| 53 FATAL("Failed to close process handle"); | 53 FATAL("Failed to close process handle"); |
| 54 } | 54 } |
| 55 success = CloseHandle(exit_pipe_); | 55 success = CloseHandle(exit_pipe_); |
| 56 if (!success) { | 56 if (!success) { |
| 57 FATAL("Failed to close process exit code pipe"); | 57 FATAL("Failed to close process exit code pipe"); |
| 58 } | 58 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 87 class ProcessInfoList { | 87 class ProcessInfoList { |
| 88 public: | 88 public: |
| 89 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { | 89 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { |
| 90 // Register a callback to extract the exit code, when the process | 90 // Register a callback to extract the exit code, when the process |
| 91 // is signaled. The callback runs in a independent thread from the OS pool. | 91 // is signaled. The callback runs in a independent thread from the OS pool. |
| 92 // Because the callback depends on the process list containing | 92 // Because the callback depends on the process list containing |
| 93 // the process, lock the mutex until the process is added to the list. | 93 // the process, lock the mutex until the process is added to the list. |
| 94 MutexLocker locker(mutex_); | 94 MutexLocker locker(mutex_); |
| 95 HANDLE wait_handle = INVALID_HANDLE_VALUE; | 95 HANDLE wait_handle = INVALID_HANDLE_VALUE; |
| 96 BOOL success = RegisterWaitForSingleObject( | 96 BOOL success = RegisterWaitForSingleObject( |
| 97 &wait_handle, | 97 &wait_handle, handle, &ExitCodeCallback, reinterpret_cast<void*>(pid), |
| 98 handle, | 98 INFINITE, WT_EXECUTEONLYONCE); |
| 99 &ExitCodeCallback, | |
| 100 reinterpret_cast<void*>(pid), | |
| 101 INFINITE, | |
| 102 WT_EXECUTEONLYONCE); | |
| 103 if (!success) { | 99 if (!success) { |
| 104 FATAL("Failed to register exit code wait operation."); | 100 FATAL("Failed to register exit code wait operation."); |
| 105 } | 101 } |
| 106 ProcessInfo* info = new ProcessInfo(pid, handle, wait_handle, pipe); | 102 ProcessInfo* info = new ProcessInfo(pid, handle, wait_handle, pipe); |
| 107 // Mutate the process list under the mutex. | 103 // Mutate the process list under the mutex. |
| 108 info->set_next(active_processes_); | 104 info->set_next(active_processes_); |
| 109 active_processes_ = info; | 105 active_processes_ = info; |
| 110 } | 106 } |
| 111 | 107 |
| 112 static bool LookupProcess(DWORD pid, | 108 static bool LookupProcess(DWORD pid, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 int exit_code; | 166 int exit_code; |
| 171 ok = GetExitCodeProcess(handle, reinterpret_cast<DWORD*>(&exit_code)); | 167 ok = GetExitCodeProcess(handle, reinterpret_cast<DWORD*>(&exit_code)); |
| 172 if (!ok) { | 168 if (!ok) { |
| 173 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); | 169 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); |
| 174 } | 170 } |
| 175 int negative = 0; | 171 int negative = 0; |
| 176 if (exit_code < 0) { | 172 if (exit_code < 0) { |
| 177 exit_code = abs(exit_code); | 173 exit_code = abs(exit_code); |
| 178 negative = 1; | 174 negative = 1; |
| 179 } | 175 } |
| 180 int message[2] = { exit_code, negative }; | 176 int message[2] = {exit_code, negative}; |
| 181 DWORD written; | 177 DWORD written; |
| 182 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); | 178 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); |
| 183 // If the process has been closed, the read end of the exit | 179 // If the process has been closed, the read end of the exit |
| 184 // pipe has been closed. It is therefore not a problem that | 180 // pipe has been closed. It is therefore not a problem that |
| 185 // WriteFile fails with a closed pipe error | 181 // WriteFile fails with a closed pipe error |
| 186 // (ERROR_NO_DATA). Other errors should not happen. | 182 // (ERROR_NO_DATA). Other errors should not happen. |
| 187 if (ok && (written != sizeof(message))) { | 183 if (ok && (written != sizeof(message))) { |
| 188 FATAL("Failed to write entire process exit message"); | 184 FATAL("Failed to write entire process exit message"); |
| 189 } else if (!ok && (GetLastError() != ERROR_NO_DATA)) { | 185 } else if (!ok && (GetLastError() != ERROR_NO_DATA)) { |
| 190 FATAL1("Failed to write exit code: %d", GetLastError()); | 186 FATAL1("Failed to write exit code: %d", GetLastError()); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 203 DISALLOW_ALLOCATION(); | 199 DISALLOW_ALLOCATION(); |
| 204 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | 200 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); |
| 205 }; | 201 }; |
| 206 | 202 |
| 207 | 203 |
| 208 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 204 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
| 209 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 205 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
| 210 | 206 |
| 211 | 207 |
| 212 // Types of pipes to create. | 208 // Types of pipes to create. |
| 213 enum NamedPipeType { | 209 enum NamedPipeType { kInheritRead, kInheritWrite, kInheritNone }; |
| 214 kInheritRead, | |
| 215 kInheritWrite, | |
| 216 kInheritNone | |
| 217 }; | |
| 218 | 210 |
| 219 | 211 |
| 220 // Create a pipe for communicating with a new process. The handles array | 212 // Create a pipe for communicating with a new process. The handles array |
| 221 // will contain the read and write ends of the pipe. Based on the type | 213 // will contain the read and write ends of the pipe. Based on the type |
| 222 // one of the handles will be inheritable. | 214 // one of the handles will be inheritable. |
| 223 // NOTE: If this function returns false the handles might have been allocated | 215 // NOTE: If this function returns false the handles might have been allocated |
| 224 // and the caller should make sure to close them in case of an error. | 216 // and the caller should make sure to close them in case of an error. |
| 225 static bool CreateProcessPipe(HANDLE handles[2], | 217 static bool CreateProcessPipe(HANDLE handles[2], |
| 226 wchar_t* pipe_name, | 218 wchar_t* pipe_name, |
| 227 NamedPipeType type) { | 219 NamedPipeType type) { |
| 228 // Security attributes describing an inheritable handle. | 220 // Security attributes describing an inheritable handle. |
| 229 SECURITY_ATTRIBUTES inherit_handle; | 221 SECURITY_ATTRIBUTES inherit_handle; |
| 230 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); | 222 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 231 inherit_handle.bInheritHandle = TRUE; | 223 inherit_handle.bInheritHandle = TRUE; |
| 232 inherit_handle.lpSecurityDescriptor = NULL; | 224 inherit_handle.lpSecurityDescriptor = NULL; |
| 233 | 225 |
| 234 if (type == kInheritRead) { | 226 if (type == kInheritRead) { |
| 235 handles[kWriteHandle] = | 227 handles[kWriteHandle] = |
| 236 CreateNamedPipeW(pipe_name, | 228 CreateNamedPipeW(pipe_name, PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, |
| 237 PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED, | |
| 238 PIPE_TYPE_BYTE | PIPE_WAIT, | 229 PIPE_TYPE_BYTE | PIPE_WAIT, |
| 239 1, // Number of pipes | 230 1, // Number of pipes |
| 240 1024, // Out buffer size | 231 1024, // Out buffer size |
| 241 1024, // In buffer size | 232 1024, // In buffer size |
| 242 0, // Timeout in ms | 233 0, // Timeout in ms |
| 243 NULL); | 234 NULL); |
| 244 | 235 |
| 245 if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) { | 236 if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 246 Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError()); | 237 Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError()); |
| 247 return false; | 238 return false; |
| 248 } | 239 } |
| 249 | 240 |
| 250 handles[kReadHandle] = | 241 handles[kReadHandle] = |
| 251 CreateFileW(pipe_name, | 242 CreateFileW(pipe_name, GENERIC_READ, 0, &inherit_handle, OPEN_EXISTING, |
| 252 GENERIC_READ, | 243 FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, NULL); |
| 253 0, | |
| 254 &inherit_handle, | |
| 255 OPEN_EXISTING, | |
| 256 FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, | |
| 257 NULL); | |
| 258 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { | 244 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { |
| 259 Log::PrintErr("CreateFile failed %d\n", GetLastError()); | 245 Log::PrintErr("CreateFile failed %d\n", GetLastError()); |
| 260 return false; | 246 return false; |
| 261 } | 247 } |
| 262 } else { | 248 } else { |
| 263 ASSERT((type == kInheritWrite) || (type == kInheritNone)); | 249 ASSERT((type == kInheritWrite) || (type == kInheritNone)); |
| 264 handles[kReadHandle] = | 250 handles[kReadHandle] = |
| 265 CreateNamedPipeW(pipe_name, | 251 CreateNamedPipeW(pipe_name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, |
| 266 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, | |
| 267 PIPE_TYPE_BYTE | PIPE_WAIT, | 252 PIPE_TYPE_BYTE | PIPE_WAIT, |
| 268 1, // Number of pipes | 253 1, // Number of pipes |
| 269 1024, // Out buffer size | 254 1024, // Out buffer size |
| 270 1024, // In buffer size | 255 1024, // In buffer size |
| 271 0, // Timeout in ms | 256 0, // Timeout in ms |
| 272 NULL); | 257 NULL); |
| 273 | 258 |
| 274 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { | 259 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { |
| 275 Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError()); | 260 Log::PrintErr("CreateNamedPipe failed %d\n", GetLastError()); |
| 276 return false; | 261 return false; |
| 277 } | 262 } |
| 278 | 263 |
| 279 handles[kWriteHandle] = | 264 handles[kWriteHandle] = CreateFileW( |
| 280 CreateFileW(pipe_name, | 265 pipe_name, GENERIC_WRITE, 0, |
| 281 GENERIC_WRITE, | 266 (type == kInheritWrite) ? &inherit_handle : NULL, OPEN_EXISTING, |
| 282 0, | 267 FILE_WRITE_ATTRIBUTES | FILE_FLAG_OVERLAPPED, NULL); |
| 283 (type == kInheritWrite) ? &inherit_handle : NULL, | |
| 284 OPEN_EXISTING, | |
| 285 FILE_WRITE_ATTRIBUTES | FILE_FLAG_OVERLAPPED, | |
| 286 NULL); | |
| 287 if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) { | 268 if (handles[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 288 Log::PrintErr("CreateFile failed %d\n", GetLastError()); | 269 Log::PrintErr("CreateFile failed %d\n", GetLastError()); |
| 289 return false; | 270 return false; |
| 290 } | 271 } |
| 291 } | 272 } |
| 292 return true; | 273 return true; |
| 293 } | 274 } |
| 294 | 275 |
| 295 | 276 |
| 296 static void CloseProcessPipe(HANDLE handles[2]) { | 277 static void CloseProcessPipe(HANDLE handles[2]) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 325 return error_code; | 306 return error_code; |
| 326 } | 307 } |
| 327 | 308 |
| 328 | 309 |
| 329 // Open an inheritable handle to NUL. | 310 // Open an inheritable handle to NUL. |
| 330 static HANDLE OpenNul() { | 311 static HANDLE OpenNul() { |
| 331 SECURITY_ATTRIBUTES inherit_handle; | 312 SECURITY_ATTRIBUTES inherit_handle; |
| 332 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); | 313 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 333 inherit_handle.bInheritHandle = TRUE; | 314 inherit_handle.bInheritHandle = TRUE; |
| 334 inherit_handle.lpSecurityDescriptor = NULL; | 315 inherit_handle.lpSecurityDescriptor = NULL; |
| 335 HANDLE nul = CreateFile(L"NUL", | 316 HANDLE nul = CreateFile(L"NUL", GENERIC_READ | GENERIC_WRITE, 0, |
| 336 GENERIC_READ | GENERIC_WRITE, | 317 &inherit_handle, OPEN_EXISTING, 0, NULL); |
| 337 0, | |
| 338 &inherit_handle, | |
| 339 OPEN_EXISTING, | |
| 340 0, | |
| 341 NULL); | |
| 342 if (nul == INVALID_HANDLE_VALUE) { | 318 if (nul == INVALID_HANDLE_VALUE) { |
| 343 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); | 319 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); |
| 344 } | 320 } |
| 345 return nul; | 321 return nul; |
| 346 } | 322 } |
| 347 | 323 |
| 348 | 324 |
| 349 typedef BOOL (WINAPI *InitProcThreadAttrListFn)( | 325 typedef BOOL(WINAPI* InitProcThreadAttrListFn)(LPPROC_THREAD_ATTRIBUTE_LIST, |
| 350 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T); | 326 DWORD, |
| 327 DWORD, |
| 328 PSIZE_T); |
| 351 | 329 |
| 352 typedef BOOL (WINAPI *UpdateProcThreadAttrFn)( | 330 typedef BOOL(WINAPI* UpdateProcThreadAttrFn)(LPPROC_THREAD_ATTRIBUTE_LIST, |
| 353 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, | 331 DWORD, |
| 354 PVOID, SIZE_T, PVOID, PSIZE_T); | 332 DWORD_PTR, |
| 333 PVOID, |
| 334 SIZE_T, |
| 335 PVOID, |
| 336 PSIZE_T); |
| 355 | 337 |
| 356 typedef VOID (WINAPI *DeleteProcThreadAttrListFn)( | 338 typedef VOID(WINAPI* DeleteProcThreadAttrListFn)(LPPROC_THREAD_ATTRIBUTE_LIST); |
| 357 LPPROC_THREAD_ATTRIBUTE_LIST); | |
| 358 | 339 |
| 359 | 340 |
| 360 static InitProcThreadAttrListFn init_proc_thread_attr_list = NULL; | 341 static InitProcThreadAttrListFn init_proc_thread_attr_list = NULL; |
| 361 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; | 342 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; |
| 362 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; | 343 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; |
| 363 | 344 |
| 364 | 345 |
| 365 static bool EnsureInitialized() { | 346 static bool EnsureInitialized() { |
| 366 static bool load_attempted = false; | 347 static bool load_attempted = false; |
| 367 static Mutex* mutex = new Mutex(); | 348 static Mutex* mutex = new Mutex(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 378 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( | 359 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( |
| 379 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")); | 360 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")); |
| 380 load_attempted = true; | 361 load_attempted = true; |
| 381 return (delete_proc_thread_attr_list != NULL); | 362 return (delete_proc_thread_attr_list != NULL); |
| 382 } | 363 } |
| 383 return (delete_proc_thread_attr_list != NULL); | 364 return (delete_proc_thread_attr_list != NULL); |
| 384 } | 365 } |
| 385 | 366 |
| 386 | 367 |
| 387 const int kMaxPipeNameSize = 80; | 368 const int kMaxPipeNameSize = 80; |
| 388 template<int Count> | 369 template <int Count> |
| 389 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { | 370 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { |
| 390 UUID uuid; | 371 UUID uuid; |
| 391 RPC_STATUS status = UuidCreateSequential(&uuid); | 372 RPC_STATUS status = UuidCreateSequential(&uuid); |
| 392 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { | 373 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { |
| 393 return status; | 374 return status; |
| 394 } | 375 } |
| 395 RPC_WSTR uuid_string; | 376 RPC_WSTR uuid_string; |
| 396 status = UuidToStringW(&uuid, &uuid_string); | 377 status = UuidToStringW(&uuid, &uuid_string); |
| 397 if (status != RPC_S_OK) { | 378 if (status != RPC_S_OK) { |
| 398 return status; | 379 return status; |
| 399 } | 380 } |
| 400 for (int i = 0; i < Count; i++) { | 381 for (int i = 0; i < Count; i++) { |
| 401 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; | 382 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
| 402 _snwprintf(pipe_names[i], | 383 _snwprintf(pipe_names[i], kMaxPipeNameSize, L"%s_%s_%d", prefix, |
| 403 kMaxPipeNameSize, | 384 uuid_string, i + 1); |
| 404 L"%s_%s_%d", prefix, uuid_string, i + 1); | |
| 405 } | 385 } |
| 406 status = RpcStringFreeW(&uuid_string); | 386 status = RpcStringFreeW(&uuid_string); |
| 407 if (status != RPC_S_OK) { | 387 if (status != RPC_S_OK) { |
| 408 return status; | 388 return status; |
| 409 } | 389 } |
| 410 return 0; | 390 return 0; |
| 411 } | 391 } |
| 412 | 392 |
| 413 | 393 |
| 414 class ProcessStarter { | 394 class ProcessStarter { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 443 stderr_handles_[kWriteHandle] = INVALID_HANDLE_VALUE; | 423 stderr_handles_[kWriteHandle] = INVALID_HANDLE_VALUE; |
| 444 exit_handles_[kReadHandle] = INVALID_HANDLE_VALUE; | 424 exit_handles_[kReadHandle] = INVALID_HANDLE_VALUE; |
| 445 exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE; | 425 exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE; |
| 446 | 426 |
| 447 // Transform input strings to system format. | 427 // Transform input strings to system format. |
| 448 const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path_); | 428 const wchar_t* system_path = StringUtilsWin::Utf8ToWide(path_); |
| 449 wchar_t** system_arguments; | 429 wchar_t** system_arguments; |
| 450 system_arguments = reinterpret_cast<wchar_t**>( | 430 system_arguments = reinterpret_cast<wchar_t**>( |
| 451 Dart_ScopeAllocate(arguments_length * sizeof(*system_arguments))); | 431 Dart_ScopeAllocate(arguments_length * sizeof(*system_arguments))); |
| 452 for (int i = 0; i < arguments_length; i++) { | 432 for (int i = 0; i < arguments_length; i++) { |
| 453 system_arguments[i] = StringUtilsWin::Utf8ToWide(arguments[i]); | 433 system_arguments[i] = StringUtilsWin::Utf8ToWide(arguments[i]); |
| 454 } | 434 } |
| 455 | 435 |
| 456 // Compute command-line length. | 436 // Compute command-line length. |
| 457 int command_line_length = wcslen(system_path); | 437 int command_line_length = wcslen(system_path); |
| 458 for (int i = 0; i < arguments_length; i++) { | 438 for (int i = 0; i < arguments_length; i++) { |
| 459 command_line_length += wcslen(system_arguments[i]); | 439 command_line_length += wcslen(system_arguments[i]); |
| 460 } | 440 } |
| 461 // Account for null termination and one space per argument. | 441 // Account for null termination and one space per argument. |
| 462 command_line_length += arguments_length + 1; | 442 command_line_length += arguments_length + 1; |
| 463 | 443 |
| 464 // Put together command-line string. | 444 // Put together command-line string. |
| 465 command_line_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate( | 445 command_line_ = reinterpret_cast<wchar_t*>( |
| 466 command_line_length * sizeof(*command_line_))); | 446 Dart_ScopeAllocate(command_line_length * sizeof(*command_line_))); |
| 467 int len = 0; | 447 int len = 0; |
| 468 int remaining = command_line_length; | 448 int remaining = command_line_length; |
| 469 int written = | 449 int written = |
| 470 _snwprintf(command_line_ + len, remaining, L"%s", system_path); | 450 _snwprintf(command_line_ + len, remaining, L"%s", system_path); |
| 471 len += written; | 451 len += written; |
| 472 remaining -= written; | 452 remaining -= written; |
| 473 ASSERT(remaining >= 0); | 453 ASSERT(remaining >= 0); |
| 474 for (int i = 0; i < arguments_length; i++) { | 454 for (int i = 0; i < arguments_length; i++) { |
| 475 written = _snwprintf( | 455 written = _snwprintf(command_line_ + len, remaining, L" %s", |
| 476 command_line_ + len, remaining, L" %s", system_arguments[i]); | 456 system_arguments[i]); |
| 477 len += written; | 457 len += written; |
| 478 remaining -= written; | 458 remaining -= written; |
| 479 ASSERT(remaining >= 0); | 459 ASSERT(remaining >= 0); |
| 480 } | 460 } |
| 481 | 461 |
| 482 // Create environment block if an environment is supplied. | 462 // Create environment block if an environment is supplied. |
| 483 environment_block_ = NULL; | 463 environment_block_ = NULL; |
| 484 if (environment != NULL) { | 464 if (environment != NULL) { |
| 485 wchar_t** system_environment; | 465 wchar_t** system_environment; |
| 486 system_environment = reinterpret_cast<wchar_t**>( | 466 system_environment = reinterpret_cast<wchar_t**>( |
| 487 Dart_ScopeAllocate(environment_length * sizeof(*system_environment))); | 467 Dart_ScopeAllocate(environment_length * sizeof(*system_environment))); |
| 488 // Convert environment strings to system strings. | 468 // Convert environment strings to system strings. |
| 489 for (intptr_t i = 0; i < environment_length; i++) { | 469 for (intptr_t i = 0; i < environment_length; i++) { |
| 490 system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]); | 470 system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]); |
| 491 } | 471 } |
| 492 | 472 |
| 493 // An environment block is a sequence of zero-terminated strings | 473 // An environment block is a sequence of zero-terminated strings |
| 494 // followed by a block-terminating zero char. | 474 // followed by a block-terminating zero char. |
| 495 intptr_t block_size = 1; | 475 intptr_t block_size = 1; |
| 496 for (intptr_t i = 0; i < environment_length; i++) { | 476 for (intptr_t i = 0; i < environment_length; i++) { |
| 497 block_size += wcslen(system_environment[i]) + 1; | 477 block_size += wcslen(system_environment[i]) + 1; |
| 498 } | 478 } |
| 499 environment_block_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate( | 479 environment_block_ = reinterpret_cast<wchar_t*>( |
| 500 block_size * sizeof(*environment_block_))); | 480 Dart_ScopeAllocate(block_size * sizeof(*environment_block_))); |
| 501 intptr_t block_index = 0; | 481 intptr_t block_index = 0; |
| 502 for (intptr_t i = 0; i < environment_length; i++) { | 482 for (intptr_t i = 0; i < environment_length; i++) { |
| 503 intptr_t len = wcslen(system_environment[i]); | 483 intptr_t len = wcslen(system_environment[i]); |
| 504 intptr_t result = _snwprintf(environment_block_ + block_index, | 484 intptr_t result = _snwprintf(environment_block_ + block_index, len, |
| 505 len, | 485 L"%s", system_environment[i]); |
| 506 L"%s", | |
| 507 system_environment[i]); | |
| 508 ASSERT(result == len); | 486 ASSERT(result == len); |
| 509 block_index += len; | 487 block_index += len; |
| 510 environment_block_[block_index++] = '\0'; | 488 environment_block_[block_index++] = '\0'; |
| 511 } | 489 } |
| 512 // Block-terminating zero char. | 490 // Block-terminating zero char. |
| 513 environment_block_[block_index++] = '\0'; | 491 environment_block_[block_index++] = '\0'; |
| 514 ASSERT(block_index == block_size); | 492 ASSERT(block_index == block_size); |
| 515 } | 493 } |
| 516 | 494 |
| 517 system_working_directory_ = NULL; | 495 system_working_directory_ = NULL; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 558 (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { | 536 (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { |
| 559 return CleanupAndReturnError(); | 537 return CleanupAndReturnError(); |
| 560 } | 538 } |
| 561 attribute_list_ = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>( | 539 attribute_list_ = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>( |
| 562 Dart_ScopeAllocate(size)); | 540 Dart_ScopeAllocate(size)); |
| 563 ZeroMemory(attribute_list_, size); | 541 ZeroMemory(attribute_list_, size); |
| 564 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) { | 542 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) { |
| 565 return CleanupAndReturnError(); | 543 return CleanupAndReturnError(); |
| 566 } | 544 } |
| 567 static const int kNumInheritedHandles = 3; | 545 static const int kNumInheritedHandles = 3; |
| 568 HANDLE inherited_handles[kNumInheritedHandles] = | 546 HANDLE inherited_handles[kNumInheritedHandles] = { |
| 569 { stdin_handles_[kReadHandle], | 547 stdin_handles_[kReadHandle], stdout_handles_[kWriteHandle], |
| 570 stdout_handles_[kWriteHandle], | 548 stderr_handles_[kWriteHandle]}; |
| 571 stderr_handles_[kWriteHandle] }; | 549 if (!update_proc_thread_attr( |
| 572 if (!update_proc_thread_attr(attribute_list_, | 550 attribute_list_, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, |
| 573 0, | 551 inherited_handles, kNumInheritedHandles * sizeof(HANDLE), NULL, |
| 574 PROC_THREAD_ATTRIBUTE_HANDLE_LIST, | 552 NULL)) { |
| 575 inherited_handles, | |
| 576 kNumInheritedHandles * sizeof(HANDLE), | |
| 577 NULL, | |
| 578 NULL)) { | |
| 579 return CleanupAndReturnError(); | 553 return CleanupAndReturnError(); |
| 580 } | 554 } |
| 581 startup_info.lpAttributeList = attribute_list_; | 555 startup_info.lpAttributeList = attribute_list_; |
| 582 } | 556 } |
| 583 | 557 |
| 584 PROCESS_INFORMATION process_info; | 558 PROCESS_INFORMATION process_info; |
| 585 ZeroMemory(&process_info, sizeof(process_info)); | 559 ZeroMemory(&process_info, sizeof(process_info)); |
| 586 | 560 |
| 587 // Create process. | 561 // Create process. |
| 588 DWORD creation_flags = | 562 DWORD creation_flags = |
| 589 EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT; | 563 EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT; |
| 590 if (mode_ != kNormal) { | 564 if (mode_ != kNormal) { |
| 591 creation_flags |= DETACHED_PROCESS; | 565 creation_flags |= DETACHED_PROCESS; |
| 592 } | 566 } |
| 593 BOOL result = CreateProcessW(NULL, // ApplicationName | 567 BOOL result = CreateProcessW( |
| 594 command_line_, | 568 NULL, // ApplicationName |
| 595 NULL, // ProcessAttributes | 569 command_line_, |
| 596 NULL, // ThreadAttributes | 570 NULL, // ProcessAttributes |
| 597 TRUE, // InheritHandles | 571 NULL, // ThreadAttributes |
| 598 creation_flags, | 572 TRUE, // InheritHandles |
| 599 environment_block_, | 573 creation_flags, environment_block_, system_working_directory_, |
| 600 system_working_directory_, | 574 reinterpret_cast<STARTUPINFOW*>(&startup_info), &process_info); |
| 601 reinterpret_cast<STARTUPINFOW*>(&startup_info), | |
| 602 &process_info); | |
| 603 | 575 |
| 604 if (result == 0) { | 576 if (result == 0) { |
| 605 return CleanupAndReturnError(); | 577 return CleanupAndReturnError(); |
| 606 } | 578 } |
| 607 | 579 |
| 608 CloseHandle(stdin_handles_[kReadHandle]); | 580 CloseHandle(stdin_handles_[kReadHandle]); |
| 609 CloseHandle(stdout_handles_[kWriteHandle]); | 581 CloseHandle(stdout_handles_[kWriteHandle]); |
| 610 CloseHandle(stderr_handles_[kWriteHandle]); | 582 CloseHandle(stderr_handles_[kWriteHandle]); |
| 611 if (mode_ == kNormal) { | 583 if (mode_ == kNormal) { |
| 612 ProcessInfoList::AddProcess(process_info.dwProcessId, | 584 ProcessInfoList::AddProcess(process_info.dwProcessId, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 675 if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { | 647 if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 676 return CleanupAndReturnError(); | 648 return CleanupAndReturnError(); |
| 677 } | 649 } |
| 678 } | 650 } |
| 679 return 0; | 651 return 0; |
| 680 } | 652 } |
| 681 | 653 |
| 682 | 654 |
| 683 int CleanupAndReturnError() { | 655 int CleanupAndReturnError() { |
| 684 int error_code = SetOsErrorMessage(os_error_message_); | 656 int error_code = SetOsErrorMessage(os_error_message_); |
| 685 CloseProcessPipes( | 657 CloseProcessPipes(stdin_handles_, stdout_handles_, stderr_handles_, |
| 686 stdin_handles_, stdout_handles_, stderr_handles_, exit_handles_); | 658 exit_handles_); |
| 687 return error_code; | 659 return error_code; |
| 688 } | 660 } |
| 689 | 661 |
| 690 | 662 |
| 691 HANDLE stdin_handles_[2]; | 663 HANDLE stdin_handles_[2]; |
| 692 HANDLE stdout_handles_[2]; | 664 HANDLE stdout_handles_[2]; |
| 693 HANDLE stderr_handles_[2]; | 665 HANDLE stderr_handles_[2]; |
| 694 HANDLE exit_handles_[2]; | 666 HANDLE exit_handles_[2]; |
| 695 | 667 |
| 696 const wchar_t* system_working_directory_; | 668 const wchar_t* system_working_directory_; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 720 const char* working_directory, | 692 const char* working_directory, |
| 721 char* environment[], | 693 char* environment[], |
| 722 intptr_t environment_length, | 694 intptr_t environment_length, |
| 723 ProcessStartMode mode, | 695 ProcessStartMode mode, |
| 724 intptr_t* in, | 696 intptr_t* in, |
| 725 intptr_t* out, | 697 intptr_t* out, |
| 726 intptr_t* err, | 698 intptr_t* err, |
| 727 intptr_t* id, | 699 intptr_t* id, |
| 728 intptr_t* exit_handler, | 700 intptr_t* exit_handler, |
| 729 char** os_error_message) { | 701 char** os_error_message) { |
| 730 ProcessStarter starter(path, | 702 ProcessStarter starter(path, arguments, arguments_length, working_directory, |
| 731 arguments, | 703 environment, environment_length, mode, in, out, err, |
| 732 arguments_length, | 704 id, exit_handler, os_error_message); |
| 733 working_directory, | |
| 734 environment, | |
| 735 environment_length, | |
| 736 mode, | |
| 737 in, | |
| 738 out, | |
| 739 err, | |
| 740 id, | |
| 741 exit_handler, | |
| 742 os_error_message); | |
| 743 return starter.Start(); | 705 return starter.Start(); |
| 744 } | 706 } |
| 745 | 707 |
| 746 | 708 |
| 747 class BufferList: public BufferListBase { | 709 class BufferList : public BufferListBase { |
| 748 public: | 710 public: |
| 749 BufferList() : read_pending_(true) { } | 711 BufferList() : read_pending_(true) {} |
| 750 | 712 |
| 751 // Indicate that data has been read into the buffer provided to | 713 // Indicate that data has been read into the buffer provided to |
| 752 // overlapped read. | 714 // overlapped read. |
| 753 void DataIsRead(intptr_t size) { | 715 void DataIsRead(intptr_t size) { |
| 754 ASSERT(read_pending_ == true); | 716 ASSERT(read_pending_ == true); |
| 755 data_size_ += size; | 717 data_size_ += size; |
| 756 free_size_ -= size; | 718 free_size_ -= size; |
| 757 ASSERT(free_size_ >= 0); | 719 ASSERT(free_size_ >= 0); |
| 758 read_pending_ = false; | 720 read_pending_ = false; |
| 759 } | 721 } |
| 760 | 722 |
| 761 // The access to the read buffer for overlapped read. | 723 // The access to the read buffer for overlapped read. |
| 762 void GetReadBuffer(uint8_t** buffer, intptr_t* size) { | 724 void GetReadBuffer(uint8_t** buffer, intptr_t* size) { |
| 763 ASSERT(!read_pending_); | 725 ASSERT(!read_pending_); |
| 764 if (free_size_ == 0) { | 726 if (free_size_ == 0) { |
| 765 Allocate(); | 727 Allocate(); |
| 766 } | 728 } |
| 767 ASSERT(free_size_ > 0); | 729 ASSERT(free_size_ > 0); |
| 768 ASSERT(free_size_ <= kBufferSize); | 730 ASSERT(free_size_ <= kBufferSize); |
| 769 *buffer = FreeSpaceAddress(); | 731 *buffer = FreeSpaceAddress(); |
| 770 *size = free_size_; | 732 *size = free_size_; |
| 771 read_pending_ = true; | 733 read_pending_ = true; |
| 772 } | 734 } |
| 773 | 735 |
| 774 intptr_t GetDataSize() { | 736 intptr_t GetDataSize() { return data_size_; } |
| 775 return data_size_; | |
| 776 } | |
| 777 | 737 |
| 778 uint8_t* GetFirstDataBuffer() { | 738 uint8_t* GetFirstDataBuffer() { |
| 779 ASSERT(head_ != NULL); | 739 ASSERT(head_ != NULL); |
| 780 ASSERT(head_ == tail_); | 740 ASSERT(head_ == tail_); |
| 781 ASSERT(data_size_ <= kBufferSize); | 741 ASSERT(data_size_ <= kBufferSize); |
| 782 return head_->data_; | 742 return head_->data_; |
| 783 } | 743 } |
| 784 | 744 |
| 785 void FreeDataBuffer() { | 745 void FreeDataBuffer() { Free(); } |
| 786 Free(); | |
| 787 } | |
| 788 | 746 |
| 789 private: | 747 private: |
| 790 bool read_pending_; | 748 bool read_pending_; |
| 791 | 749 |
| 792 DISALLOW_COPY_AND_ASSIGN(BufferList); | 750 DISALLOW_COPY_AND_ASSIGN(BufferList); |
| 793 }; | 751 }; |
| 794 | 752 |
| 795 | 753 |
| 796 class OverlappedHandle { | 754 class OverlappedHandle { |
| 797 public: | 755 public: |
| 798 OverlappedHandle() {} | 756 OverlappedHandle() {} |
| 799 | 757 |
| 800 void Init(HANDLE handle, HANDLE event) { | 758 void Init(HANDLE handle, HANDLE event) { |
| 801 handle_ = handle; | 759 handle_ = handle; |
| 802 event_ = event; | 760 event_ = event; |
| 803 ClearOverlapped(); | 761 ClearOverlapped(); |
| 804 } | 762 } |
| 805 | 763 |
| 806 bool HasEvent(HANDLE event) { | 764 bool HasEvent(HANDLE event) { return (event_ == event); } |
| 807 return (event_ == event); | |
| 808 } | |
| 809 | 765 |
| 810 bool Read() { | 766 bool Read() { |
| 811 // Get the data read as a result of a completed overlapped operation. | 767 // Get the data read as a result of a completed overlapped operation. |
| 812 if (overlapped_.InternalHigh > 0) { | 768 if (overlapped_.InternalHigh > 0) { |
| 813 buffer_.DataIsRead(overlapped_.InternalHigh); | 769 buffer_.DataIsRead(overlapped_.InternalHigh); |
| 814 } else { | 770 } else { |
| 815 buffer_.DataIsRead(0); | 771 buffer_.DataIsRead(0); |
| 816 } | 772 } |
| 817 | 773 |
| 818 // Keep reading until error or pending operation. | 774 // Keep reading until error or pending operation. |
| 819 while (true) { | 775 while (true) { |
| 820 ClearOverlapped(); | 776 ClearOverlapped(); |
| 821 uint8_t* buffer; | 777 uint8_t* buffer; |
| 822 intptr_t buffer_size; | 778 intptr_t buffer_size; |
| 823 buffer_.GetReadBuffer(&buffer, &buffer_size); | 779 buffer_.GetReadBuffer(&buffer, &buffer_size); |
| 824 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_); | 780 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_); |
| 825 if (!ok) { | 781 if (!ok) { |
| 826 return (GetLastError() == ERROR_IO_PENDING); | 782 return (GetLastError() == ERROR_IO_PENDING); |
| 827 } | 783 } |
| 828 buffer_.DataIsRead(overlapped_.InternalHigh); | 784 buffer_.DataIsRead(overlapped_.InternalHigh); |
| 829 } | 785 } |
| 830 } | 786 } |
| 831 | 787 |
| 832 Dart_Handle GetData() { | 788 Dart_Handle GetData() { return buffer_.GetData(); } |
| 833 return buffer_.GetData(); | |
| 834 } | |
| 835 | 789 |
| 836 intptr_t GetDataSize() { | 790 intptr_t GetDataSize() { return buffer_.GetDataSize(); } |
| 837 return buffer_.GetDataSize(); | |
| 838 } | |
| 839 | 791 |
| 840 uint8_t* GetFirstDataBuffer() { | 792 uint8_t* GetFirstDataBuffer() { return buffer_.GetFirstDataBuffer(); } |
| 841 return buffer_.GetFirstDataBuffer(); | |
| 842 } | |
| 843 | 793 |
| 844 void FreeDataBuffer() { | 794 void FreeDataBuffer() { return buffer_.FreeDataBuffer(); } |
| 845 return buffer_.FreeDataBuffer(); | |
| 846 } | |
| 847 | 795 |
| 848 void Close() { | 796 void Close() { |
| 849 CloseHandle(handle_); | 797 CloseHandle(handle_); |
| 850 CloseHandle(event_); | 798 CloseHandle(event_); |
| 851 handle_ = INVALID_HANDLE_VALUE; | 799 handle_ = INVALID_HANDLE_VALUE; |
| 852 overlapped_.hEvent = INVALID_HANDLE_VALUE; | 800 overlapped_.hEvent = INVALID_HANDLE_VALUE; |
| 853 } | 801 } |
| 854 | 802 |
| 855 private: | 803 private: |
| 856 void ClearOverlapped() { | 804 void ClearOverlapped() { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 949 return true; | 897 return true; |
| 950 } | 898 } |
| 951 | 899 |
| 952 | 900 |
| 953 bool Process::Kill(intptr_t id, int signal) { | 901 bool Process::Kill(intptr_t id, int signal) { |
| 954 USE(signal); // signal is not used on Windows. | 902 USE(signal); // signal is not used on Windows. |
| 955 HANDLE process_handle; | 903 HANDLE process_handle; |
| 956 HANDLE wait_handle; | 904 HANDLE wait_handle; |
| 957 HANDLE exit_pipe; | 905 HANDLE exit_pipe; |
| 958 // First check the process info list for the process to get a handle to it. | 906 // First check the process info list for the process to get a handle to it. |
| 959 bool success = ProcessInfoList::LookupProcess(id, | 907 bool success = ProcessInfoList::LookupProcess(id, &process_handle, |
| 960 &process_handle, | 908 &wait_handle, &exit_pipe); |
| 961 &wait_handle, | |
| 962 &exit_pipe); | |
| 963 // For detached processes we don't have the process registered in the | 909 // For detached processes we don't have the process registered in the |
| 964 // process info list. Try to look it up through the OS. | 910 // process info list. Try to look it up through the OS. |
| 965 if (!success) { | 911 if (!success) { |
| 966 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); | 912 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); |
| 967 // The process is already dead. | 913 // The process is already dead. |
| 968 if (process_handle == INVALID_HANDLE_VALUE) { | 914 if (process_handle == INVALID_HANDLE_VALUE) { |
| 969 return false; | 915 return false; |
| 970 } | 916 } |
| 971 } | 917 } |
| 972 BOOL result = TerminateProcess(process_handle, -1); | 918 BOOL result = TerminateProcess(process_handle, -1); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 handled = true; | 950 handled = true; |
| 1005 } | 951 } |
| 1006 handler = handler->next(); | 952 handler = handler->next(); |
| 1007 } | 953 } |
| 1008 return handled; | 954 return handled; |
| 1009 } | 955 } |
| 1010 | 956 |
| 1011 | 957 |
| 1012 intptr_t GetWinSignal(intptr_t signal) { | 958 intptr_t GetWinSignal(intptr_t signal) { |
| 1013 switch (signal) { | 959 switch (signal) { |
| 1014 case kSighup: return CTRL_CLOSE_EVENT; | 960 case kSighup: |
| 1015 case kSigint: return CTRL_C_EVENT; | 961 return CTRL_CLOSE_EVENT; |
| 962 case kSigint: |
| 963 return CTRL_C_EVENT; |
| 1016 default: | 964 default: |
| 1017 return -1; | 965 return -1; |
| 1018 } | 966 } |
| 1019 } | 967 } |
| 1020 | 968 |
| 1021 | 969 |
| 1022 intptr_t Process::SetSignalHandler(intptr_t signal) { | 970 intptr_t Process::SetSignalHandler(intptr_t signal) { |
| 1023 signal = GetWinSignal(signal); | 971 signal = GetWinSignal(signal); |
| 1024 if (signal == -1) { | 972 if (signal == -1) { |
| 1025 return -1; | 973 return -1; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1082 } | 1030 } |
| 1083 delete handler; | 1031 delete handler; |
| 1084 } | 1032 } |
| 1085 | 1033 |
| 1086 } // namespace bin | 1034 } // namespace bin |
| 1087 } // namespace dart | 1035 } // namespace dart |
| 1088 | 1036 |
| 1089 #endif // defined(TARGET_OS_WINDOWS) | 1037 #endif // defined(TARGET_OS_WINDOWS) |
| 1090 | 1038 |
| 1091 #endif // !defined(DART_IO_DISABLED) | 1039 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |