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 |