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 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
7 | 7 |
8 #include "bin/process.h" | 8 #include "bin/process.h" |
9 | 9 |
10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
12 #include <poll.h> // NOLINT | 12 #include <poll.h> // NOLINT |
13 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
14 #include <stdlib.h> // NOLINT | 14 #include <stdlib.h> // NOLINT |
15 #include <string.h> // NOLINT | 15 #include <string.h> // NOLINT |
16 #include <sys/wait.h> // NOLINT | 16 #include <sys/wait.h> // NOLINT |
17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
18 | 18 |
| 19 #include "platform/signal_blocker.h" |
19 #include "bin/fdutils.h" | 20 #include "bin/fdutils.h" |
20 #include "bin/log.h" | 21 #include "bin/log.h" |
21 #include "bin/signal_blocker.h" | |
22 #include "bin/thread.h" | 22 #include "bin/thread.h" |
23 | 23 |
24 | 24 |
25 extern char **environ; | 25 extern char **environ; |
26 | 26 |
27 | 27 |
28 namespace dart { | 28 namespace dart { |
29 namespace bin { | 29 namespace bin { |
30 | 30 |
31 // ProcessInfo is used to map a process id to the file descriptor for | 31 // ProcessInfo is used to map a process id to the file descriptor for |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 144 |
145 if (!running_) { | 145 if (!running_) { |
146 return; | 146 return; |
147 } | 147 } |
148 | 148 |
149 // Set terminate_done_ to false, so we can use it as a guard for our | 149 // Set terminate_done_ to false, so we can use it as a guard for our |
150 // monitor. | 150 // monitor. |
151 running_ = false; | 151 running_ = false; |
152 | 152 |
153 // Fork to wake up waitpid. | 153 // Fork to wake up waitpid. |
154 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fork()) == 0) { | 154 if (TEMP_FAILURE_RETRY(fork()) == 0) { |
155 exit(0); | 155 exit(0); |
156 } | 156 } |
157 | 157 |
158 monitor_->Notify(); | 158 monitor_->Notify(); |
159 | 159 |
160 while (!terminate_done_) { | 160 while (!terminate_done_) { |
161 monitor_->Wait(dart::Monitor::kNoTimeout); | 161 monitor_->Wait(dart::Monitor::kNoTimeout); |
162 } | 162 } |
163 } | 163 } |
164 | 164 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 char error_buf[kBufferSize]; | 243 char error_buf[kBufferSize]; |
244 char* os_error_message = strerror_r(errno, error_buf, kBufferSize); | 244 char* os_error_message = strerror_r(errno, error_buf, kBufferSize); |
245 ASSERT(sizeof(child_errno) == sizeof(errno)); | 245 ASSERT(sizeof(child_errno) == sizeof(errno)); |
246 int bytes_written = | 246 int bytes_written = |
247 FDUtils::WriteToBlocking( | 247 FDUtils::WriteToBlocking( |
248 exec_control_fd, &child_errno, sizeof(child_errno)); | 248 exec_control_fd, &child_errno, sizeof(child_errno)); |
249 if (bytes_written == sizeof(child_errno)) { | 249 if (bytes_written == sizeof(child_errno)) { |
250 FDUtils::WriteToBlocking( | 250 FDUtils::WriteToBlocking( |
251 exec_control_fd, os_error_message, strlen(os_error_message) + 1); | 251 exec_control_fd, os_error_message, strlen(os_error_message) + 1); |
252 } | 252 } |
253 TEMP_FAILURE_RETRY(close(exec_control_fd)); | 253 VOID_TEMP_FAILURE_RETRY(close(exec_control_fd)); |
254 exit(1); | 254 exit(1); |
255 } | 255 } |
256 | 256 |
257 | 257 |
258 int Process::Start(const char* path, | 258 int Process::Start(const char* path, |
259 char* arguments[], | 259 char* arguments[], |
260 intptr_t arguments_length, | 260 intptr_t arguments_length, |
261 const char* working_directory, | 261 const char* working_directory, |
262 char* environment[], | 262 char* environment[], |
263 intptr_t environment_length, | 263 intptr_t environment_length, |
264 intptr_t* in, | 264 intptr_t* in, |
265 intptr_t* out, | 265 intptr_t* out, |
266 intptr_t* err, | 266 intptr_t* err, |
267 intptr_t* id, | 267 intptr_t* id, |
268 intptr_t* exit_event, | 268 intptr_t* exit_event, |
269 char** os_error_message) { | 269 char** os_error_message) { |
270 pid_t pid; | 270 pid_t pid; |
271 int read_in[2]; // Pipe for stdout to child process. | 271 int read_in[2]; // Pipe for stdout to child process. |
272 int read_err[2]; // Pipe for stderr to child process. | 272 int read_err[2]; // Pipe for stderr to child process. |
273 int write_out[2]; // Pipe for stdin to child process. | 273 int write_out[2]; // Pipe for stdin to child process. |
274 int exec_control[2]; // Pipe to get the result from exec. | 274 int exec_control[2]; // Pipe to get the result from exec. |
275 int result; | 275 int result; |
276 | 276 |
277 result = TEMP_FAILURE_RETRY(pipe(read_in)); | 277 result = pipe(read_in); |
278 if (result < 0) { | 278 if (result < 0) { |
279 SetChildOsErrorMessage(os_error_message); | 279 SetChildOsErrorMessage(os_error_message); |
280 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 280 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
281 return errno; | 281 return errno; |
282 } | 282 } |
283 FDUtils::SetCloseOnExec(read_in[0]); | 283 FDUtils::SetCloseOnExec(read_in[0]); |
284 | 284 |
285 result = TEMP_FAILURE_RETRY(pipe(read_err)); | 285 result = pipe(read_err); |
286 if (result < 0) { | 286 if (result < 0) { |
287 SetChildOsErrorMessage(os_error_message); | 287 SetChildOsErrorMessage(os_error_message); |
288 TEMP_FAILURE_RETRY(close(read_in[0])); | 288 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
289 TEMP_FAILURE_RETRY(close(read_in[1])); | 289 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
290 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 290 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
291 return errno; | 291 return errno; |
292 } | 292 } |
293 FDUtils::SetCloseOnExec(read_err[0]); | 293 FDUtils::SetCloseOnExec(read_err[0]); |
294 | 294 |
295 result = TEMP_FAILURE_RETRY(pipe(write_out)); | 295 result = pipe(write_out); |
296 if (result < 0) { | 296 if (result < 0) { |
297 SetChildOsErrorMessage(os_error_message); | 297 SetChildOsErrorMessage(os_error_message); |
298 TEMP_FAILURE_RETRY(close(read_in[0])); | 298 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
299 TEMP_FAILURE_RETRY(close(read_in[1])); | 299 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
300 TEMP_FAILURE_RETRY(close(read_err[0])); | 300 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
301 TEMP_FAILURE_RETRY(close(read_err[1])); | 301 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
302 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 302 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
303 return errno; | 303 return errno; |
304 } | 304 } |
305 FDUtils::SetCloseOnExec(write_out[1]); | 305 FDUtils::SetCloseOnExec(write_out[1]); |
306 | 306 |
307 result = TEMP_FAILURE_RETRY(pipe(exec_control)); | 307 result = pipe(exec_control); |
308 if (result < 0) { | 308 if (result < 0) { |
309 SetChildOsErrorMessage(os_error_message); | 309 SetChildOsErrorMessage(os_error_message); |
310 TEMP_FAILURE_RETRY(close(read_in[0])); | 310 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
311 TEMP_FAILURE_RETRY(close(read_in[1])); | 311 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
312 TEMP_FAILURE_RETRY(close(read_err[0])); | 312 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
313 TEMP_FAILURE_RETRY(close(read_err[1])); | 313 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
314 TEMP_FAILURE_RETRY(close(write_out[0])); | 314 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
315 TEMP_FAILURE_RETRY(close(write_out[1])); | 315 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
316 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 316 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
317 return errno; | 317 return errno; |
318 } | 318 } |
319 FDUtils::SetCloseOnExec(exec_control[0]); | 319 FDUtils::SetCloseOnExec(exec_control[0]); |
320 FDUtils::SetCloseOnExec(exec_control[1]); | 320 FDUtils::SetCloseOnExec(exec_control[1]); |
321 | 321 |
322 if (result < 0) { | 322 if (result < 0) { |
323 SetChildOsErrorMessage(os_error_message); | 323 SetChildOsErrorMessage(os_error_message); |
324 TEMP_FAILURE_RETRY(close(read_in[0])); | 324 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
325 TEMP_FAILURE_RETRY(close(read_in[1])); | 325 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
326 TEMP_FAILURE_RETRY(close(read_err[0])); | 326 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
327 TEMP_FAILURE_RETRY(close(read_err[1])); | 327 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
328 TEMP_FAILURE_RETRY(close(write_out[0])); | 328 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
329 TEMP_FAILURE_RETRY(close(write_out[1])); | 329 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
330 TEMP_FAILURE_RETRY(close(exec_control[0])); | 330 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
331 TEMP_FAILURE_RETRY(close(exec_control[1])); | 331 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
332 Log::PrintErr("fcntl failed: %s\n", *os_error_message); | 332 Log::PrintErr("fcntl failed: %s\n", *os_error_message); |
333 return errno; | 333 return errno; |
334 } | 334 } |
335 | 335 |
336 char** program_arguments = new char*[arguments_length + 2]; | 336 char** program_arguments = new char*[arguments_length + 2]; |
337 program_arguments[0] = const_cast<char*>(path); | 337 program_arguments[0] = const_cast<char*>(path); |
338 for (int i = 0; i < arguments_length; i++) { | 338 for (int i = 0; i < arguments_length; i++) { |
339 program_arguments[i + 1] = arguments[i]; | 339 program_arguments[i + 1] = arguments[i]; |
340 } | 340 } |
341 program_arguments[arguments_length + 1] = NULL; | 341 program_arguments[arguments_length + 1] = NULL; |
342 | 342 |
343 char** program_environment = NULL; | 343 char** program_environment = NULL; |
344 if (environment != NULL) { | 344 if (environment != NULL) { |
345 program_environment = new char*[environment_length + 1]; | 345 program_environment = new char*[environment_length + 1]; |
346 for (int i = 0; i < environment_length; i++) { | 346 for (int i = 0; i < environment_length; i++) { |
347 program_environment[i] = environment[i]; | 347 program_environment[i] = environment[i]; |
348 } | 348 } |
349 program_environment[environment_length] = NULL; | 349 program_environment[environment_length] = NULL; |
350 } | 350 } |
351 | 351 |
352 pid = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(fork()); | 352 pid = TEMP_FAILURE_RETRY(fork()); |
353 if (pid < 0) { | 353 if (pid < 0) { |
354 SetChildOsErrorMessage(os_error_message); | 354 SetChildOsErrorMessage(os_error_message); |
355 delete[] program_arguments; | 355 delete[] program_arguments; |
356 TEMP_FAILURE_RETRY(close(read_in[0])); | 356 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
357 TEMP_FAILURE_RETRY(close(read_in[1])); | 357 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
358 TEMP_FAILURE_RETRY(close(read_err[0])); | 358 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
359 TEMP_FAILURE_RETRY(close(read_err[1])); | 359 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
360 TEMP_FAILURE_RETRY(close(write_out[0])); | 360 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
361 TEMP_FAILURE_RETRY(close(write_out[1])); | 361 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
362 TEMP_FAILURE_RETRY(close(exec_control[0])); | 362 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
363 TEMP_FAILURE_RETRY(close(exec_control[1])); | 363 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
364 return errno; | 364 return errno; |
365 } else if (pid == 0) { | 365 } else if (pid == 0) { |
366 // Wait for parent process before setting up the child process. | 366 // Wait for parent process before setting up the child process. |
367 char msg; | 367 char msg; |
368 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); | 368 int bytes_read = FDUtils::ReadFromBlocking(read_in[0], &msg, sizeof(msg)); |
369 if (bytes_read != sizeof(msg)) { | 369 if (bytes_read != sizeof(msg)) { |
370 perror("Failed receiving notification message"); | 370 perror("Failed receiving notification message"); |
371 exit(1); | 371 exit(1); |
372 } | 372 } |
373 | 373 |
374 TEMP_FAILURE_RETRY(close(write_out[1])); | 374 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
375 TEMP_FAILURE_RETRY(close(read_in[0])); | 375 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
376 TEMP_FAILURE_RETRY(close(read_err[0])); | 376 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
377 TEMP_FAILURE_RETRY(close(exec_control[0])); | 377 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
378 | 378 |
379 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { | 379 if (TEMP_FAILURE_RETRY(dup2(write_out[0], STDIN_FILENO)) == -1) { |
380 ReportChildError(exec_control[1]); | 380 ReportChildError(exec_control[1]); |
381 } | 381 } |
382 TEMP_FAILURE_RETRY(close(write_out[0])); | 382 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
383 | 383 |
384 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { | 384 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { |
385 ReportChildError(exec_control[1]); | 385 ReportChildError(exec_control[1]); |
386 } | 386 } |
387 TEMP_FAILURE_RETRY(close(read_in[1])); | 387 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
388 | 388 |
389 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { | 389 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { |
390 ReportChildError(exec_control[1]); | 390 ReportChildError(exec_control[1]); |
391 } | 391 } |
392 TEMP_FAILURE_RETRY(close(read_err[1])); | 392 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
393 | 393 |
394 if (working_directory != NULL && | 394 if (working_directory != NULL && chdir(working_directory) == -1) { |
395 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { | |
396 ReportChildError(exec_control[1]); | 395 ReportChildError(exec_control[1]); |
397 } | 396 } |
398 | 397 |
399 if (program_environment != NULL) { | 398 if (program_environment != NULL) { |
400 environ = program_environment; | 399 environ = program_environment; |
401 } | 400 } |
402 | 401 |
403 TEMP_FAILURE_RETRY( | 402 execvp(path, const_cast<char* const*>(program_arguments)); |
404 execvp(path, const_cast<char* const*>(program_arguments))); | |
405 | 403 |
406 ReportChildError(exec_control[1]); | 404 ReportChildError(exec_control[1]); |
407 } | 405 } |
408 | 406 |
409 // Be sure to listen for exit-codes, now we have a child-process. | 407 // Be sure to listen for exit-codes, now we have a child-process. |
410 ExitCodeHandler::ProcessStarted(); | 408 ExitCodeHandler::ProcessStarted(); |
411 | 409 |
412 // The arguments and environment for the spawned process are not needed | 410 // The arguments and environment for the spawned process are not needed |
413 // any longer. | 411 // any longer. |
414 delete[] program_arguments; | 412 delete[] program_arguments; |
415 delete[] program_environment; | 413 delete[] program_environment; |
416 | 414 |
417 int event_fds[2]; | 415 int event_fds[2]; |
418 result = TEMP_FAILURE_RETRY(pipe(event_fds)); | 416 result = pipe(event_fds); |
419 if (result < 0) { | 417 if (result < 0) { |
420 SetChildOsErrorMessage(os_error_message); | 418 SetChildOsErrorMessage(os_error_message); |
421 TEMP_FAILURE_RETRY(close(read_in[0])); | 419 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
422 TEMP_FAILURE_RETRY(close(read_in[1])); | 420 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
423 TEMP_FAILURE_RETRY(close(read_err[0])); | 421 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
424 TEMP_FAILURE_RETRY(close(read_err[1])); | 422 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
425 TEMP_FAILURE_RETRY(close(write_out[0])); | 423 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
426 TEMP_FAILURE_RETRY(close(write_out[1])); | 424 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
427 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 425 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
428 return errno; | 426 return errno; |
429 } | 427 } |
430 FDUtils::SetCloseOnExec(event_fds[0]); | 428 FDUtils::SetCloseOnExec(event_fds[0]); |
431 FDUtils::SetCloseOnExec(event_fds[1]); | 429 FDUtils::SetCloseOnExec(event_fds[1]); |
432 | 430 |
433 ProcessInfoList::AddProcess(pid, event_fds[1]); | 431 ProcessInfoList::AddProcess(pid, event_fds[1]); |
434 *exit_event = event_fds[0]; | 432 *exit_event = event_fds[0]; |
435 FDUtils::SetNonBlocking(event_fds[0]); | 433 FDUtils::SetNonBlocking(event_fds[0]); |
436 | 434 |
437 // Notify child process to start. | 435 // Notify child process to start. |
438 char msg = '1'; | 436 char msg = '1'; |
439 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); | 437 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); |
440 if (result != sizeof(msg)) { | 438 if (result != sizeof(msg)) { |
441 perror("Failed sending notification message"); | 439 perror("Failed sending notification message"); |
442 } | 440 } |
443 | 441 |
444 // Read exec result from child. If no data is returned the exec was | 442 // Read exec result from child. If no data is returned the exec was |
445 // successful and the exec call closed the pipe. Otherwise the errno | 443 // successful and the exec call closed the pipe. Otherwise the errno |
446 // is written to the pipe. | 444 // is written to the pipe. |
447 TEMP_FAILURE_RETRY(close(exec_control[1])); | 445 VOID_TEMP_FAILURE_RETRY(close(exec_control[1])); |
448 int child_errno; | 446 int child_errno; |
449 int bytes_read = -1; | 447 int bytes_read = -1; |
450 ASSERT(sizeof(child_errno) == sizeof(errno)); | 448 ASSERT(sizeof(child_errno) == sizeof(errno)); |
451 bytes_read = | 449 bytes_read = |
452 FDUtils::ReadFromBlocking( | 450 FDUtils::ReadFromBlocking( |
453 exec_control[0], &child_errno, sizeof(child_errno)); | 451 exec_control[0], &child_errno, sizeof(child_errno)); |
454 if (bytes_read == sizeof(child_errno)) { | 452 if (bytes_read == sizeof(child_errno)) { |
455 static const int kMaxMessageSize = 256; | 453 static const int kMaxMessageSize = 256; |
456 char* message = static_cast<char*>(malloc(kMaxMessageSize)); | 454 char* message = static_cast<char*>(malloc(kMaxMessageSize)); |
457 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], | 455 bytes_read = FDUtils::ReadFromBlocking(exec_control[0], |
458 message, | 456 message, |
459 kMaxMessageSize); | 457 kMaxMessageSize); |
460 message[kMaxMessageSize - 1] = '\0'; | 458 message[kMaxMessageSize - 1] = '\0'; |
461 *os_error_message = message; | 459 *os_error_message = message; |
462 } | 460 } |
463 TEMP_FAILURE_RETRY(close(exec_control[0])); | 461 VOID_TEMP_FAILURE_RETRY(close(exec_control[0])); |
464 | 462 |
465 // Return error code if any failures. | 463 // Return error code if any failures. |
466 if (bytes_read != 0) { | 464 if (bytes_read != 0) { |
467 TEMP_FAILURE_RETRY(close(read_in[0])); | 465 VOID_TEMP_FAILURE_RETRY(close(read_in[0])); |
468 TEMP_FAILURE_RETRY(close(read_in[1])); | 466 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
469 TEMP_FAILURE_RETRY(close(read_err[0])); | 467 VOID_TEMP_FAILURE_RETRY(close(read_err[0])); |
470 TEMP_FAILURE_RETRY(close(read_err[1])); | 468 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
471 TEMP_FAILURE_RETRY(close(write_out[0])); | 469 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
472 TEMP_FAILURE_RETRY(close(write_out[1])); | 470 VOID_TEMP_FAILURE_RETRY(close(write_out[1])); |
473 | 471 |
474 // Since exec() failed, we're not interested in the exit code. | 472 // Since exec() failed, we're not interested in the exit code. |
475 // We close the reading side of the exit code pipe here. | 473 // We close the reading side of the exit code pipe here. |
476 // GetProcessExitCodes will get a broken pipe error when it tries to write | 474 // GetProcessExitCodes will get a broken pipe error when it tries to write |
477 // to the writing side of the pipe and it will ignore the error. | 475 // to the writing side of the pipe and it will ignore the error. |
478 TEMP_FAILURE_RETRY(close(*exit_event)); | 476 VOID_TEMP_FAILURE_RETRY(close(*exit_event)); |
479 *exit_event = -1; | 477 *exit_event = -1; |
480 | 478 |
481 if (bytes_read == -1) { | 479 if (bytes_read == -1) { |
482 return errno; // Read failed. | 480 return errno; // Read failed. |
483 } else { | 481 } else { |
484 return child_errno; // Exec failed. | 482 return child_errno; // Exec failed. |
485 } | 483 } |
486 } | 484 } |
487 | 485 |
488 FDUtils::SetNonBlocking(read_in[0]); | 486 FDUtils::SetNonBlocking(read_in[0]); |
489 *in = read_in[0]; | 487 *in = read_in[0]; |
490 TEMP_FAILURE_RETRY(close(read_in[1])); | 488 VOID_TEMP_FAILURE_RETRY(close(read_in[1])); |
491 FDUtils::SetNonBlocking(write_out[1]); | 489 FDUtils::SetNonBlocking(write_out[1]); |
492 *out = write_out[1]; | 490 *out = write_out[1]; |
493 TEMP_FAILURE_RETRY(close(write_out[0])); | 491 VOID_TEMP_FAILURE_RETRY(close(write_out[0])); |
494 FDUtils::SetNonBlocking(read_err[0]); | 492 FDUtils::SetNonBlocking(read_err[0]); |
495 *err = read_err[0]; | 493 *err = read_err[0]; |
496 TEMP_FAILURE_RETRY(close(read_err[1])); | 494 VOID_TEMP_FAILURE_RETRY(close(read_err[1])); |
497 | 495 |
498 *id = pid; | 496 *id = pid; |
499 return 0; | 497 return 0; |
500 } | 498 } |
501 | 499 |
502 | 500 |
503 class BufferList: public BufferListBase { | 501 class BufferList: public BufferListBase { |
504 public: | 502 public: |
505 bool Read(int fd, intptr_t available) { | 503 bool Read(int fd, intptr_t available) { |
506 // Read all available bytes. | 504 // Read all available bytes. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 intptr_t exit_code = exit_code_data.ints[0]; | 609 intptr_t exit_code = exit_code_data.ints[0]; |
612 intptr_t negative = exit_code_data.ints[1]; | 610 intptr_t negative = exit_code_data.ints[1]; |
613 if (negative) exit_code = -exit_code; | 611 if (negative) exit_code = -exit_code; |
614 result->set_exit_code(exit_code); | 612 result->set_exit_code(exit_code); |
615 | 613 |
616 return true; | 614 return true; |
617 } | 615 } |
618 | 616 |
619 | 617 |
620 bool Process::Kill(intptr_t id, int signal) { | 618 bool Process::Kill(intptr_t id, int signal) { |
621 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); | 619 return kill(id, signal) != -1; |
622 } | 620 } |
623 | 621 |
624 | 622 |
625 void Process::TerminateExitCodeHandler() { | 623 void Process::TerminateExitCodeHandler() { |
626 ExitCodeHandler::TerminateExitCodeThread(); | 624 ExitCodeHandler::TerminateExitCodeThread(); |
627 } | 625 } |
628 | 626 |
629 | 627 |
630 intptr_t Process::CurrentProcessId() { | 628 intptr_t Process::CurrentProcessId() { |
631 return static_cast<intptr_t>(getpid()); | 629 return static_cast<intptr_t>(getpid()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 intptr_t Process::SetSignalHandler(intptr_t signal) { | 664 intptr_t Process::SetSignalHandler(intptr_t signal) { |
667 bool found = false; | 665 bool found = false; |
668 for (int i = 0; i < kSignalsCount; i++) { | 666 for (int i = 0; i < kSignalsCount; i++) { |
669 if (kSignals[i] == signal) { | 667 if (kSignals[i] == signal) { |
670 found = true; | 668 found = true; |
671 break; | 669 break; |
672 } | 670 } |
673 } | 671 } |
674 if (!found) return -1; | 672 if (!found) return -1; |
675 int fds[2]; | 673 int fds[2]; |
676 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) { | 674 if (pipe(fds) != 0) { |
677 return -1; | 675 return -1; |
678 } | 676 } |
679 if (!FDUtils::SetNonBlocking(fds[0])) { | 677 if (!FDUtils::SetNonBlocking(fds[0])) { |
680 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0])); | 678 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
681 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1])); | 679 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
682 return -1; | 680 return -1; |
683 } | 681 } |
684 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 682 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
685 MutexLocker lock(signal_mutex); | 683 MutexLocker lock(signal_mutex); |
686 SignalInfo* handler = signal_handlers; | 684 SignalInfo* handler = signal_handlers; |
687 bool listen = true; | 685 bool listen = true; |
688 while (handler != NULL) { | 686 while (handler != NULL) { |
689 if (handler->signal() == signal) { | 687 if (handler->signal() == signal) { |
690 listen = false; | 688 listen = false; |
691 break; | 689 break; |
692 } | 690 } |
693 handler = handler->next(); | 691 handler = handler->next(); |
694 } | 692 } |
695 if (listen) { | 693 if (listen) { |
696 struct sigaction act; | 694 struct sigaction act; |
697 bzero(&act, sizeof(act)); | 695 bzero(&act, sizeof(act)); |
698 act.sa_handler = SignalHandler; | 696 act.sa_handler = SignalHandler; |
699 sigemptyset(&act.sa_mask); | 697 sigemptyset(&act.sa_mask); |
700 for (int i = 0; i < kSignalsCount; i++) { | 698 for (int i = 0; i < kSignalsCount; i++) { |
701 sigaddset(&act.sa_mask, kSignals[i]); | 699 sigaddset(&act.sa_mask, kSignals[i]); |
702 } | 700 } |
703 int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 701 int status = sigaction(signal, &act, NULL); |
704 sigaction(signal, &act, NULL)); | |
705 if (status < 0) { | 702 if (status < 0) { |
706 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0])); | 703 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
707 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1])); | 704 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
708 return -1; | 705 return -1; |
709 } | 706 } |
710 } | 707 } |
711 if (signal_handlers == NULL) { | 708 if (signal_handlers == NULL) { |
712 signal_handlers = new SignalInfo(fds[1], signal); | 709 signal_handlers = new SignalInfo(fds[1], signal); |
713 } else { | 710 } else { |
714 new SignalInfo(fds[1], signal, signal_handlers); | 711 new SignalInfo(fds[1], signal, signal_handlers); |
715 } | 712 } |
716 return fds[0]; | 713 return fds[0]; |
717 } | 714 } |
(...skipping 16 matching lines...) Expand all Loading... |
734 } | 731 } |
735 } | 732 } |
736 SignalInfo* next = handler->next(); | 733 SignalInfo* next = handler->next(); |
737 if (remove) delete handler; | 734 if (remove) delete handler; |
738 handler = next; | 735 handler = next; |
739 } | 736 } |
740 if (unlisten) { | 737 if (unlisten) { |
741 struct sigaction act; | 738 struct sigaction act; |
742 bzero(&act, sizeof(act)); | 739 bzero(&act, sizeof(act)); |
743 act.sa_handler = SIG_DFL; | 740 act.sa_handler = SIG_DFL; |
744 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL)); | 741 sigaction(signal, &act, NULL); |
745 } | 742 } |
746 } | 743 } |
747 | 744 |
748 } // namespace bin | 745 } // namespace bin |
749 } // namespace dart | 746 } // namespace dart |
750 | 747 |
751 #endif // defined(TARGET_OS_LINUX) | 748 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |