| OLD | NEW |
| 1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 98 } | 98 } |
| 99 } | 99 } |
| 100 return 0; | 100 return 0; |
| 101 } | 101 } |
| 102 | 102 |
| 103 | 103 |
| 104 // Suspends the thread until there is data available from the child process. | 104 // Suspends the thread until there is data available from the child process. |
| 105 // Returns false on timeout, true on data ready. | 105 // Returns false on timeout, true on data ready. |
| 106 static bool WaitOnFD(int fd, | 106 static bool WaitOnFD(int fd, |
| 107 int read_timeout, | 107 int read_timeout, |
| 108 int* total_timeout, | 108 int total_timeout, |
| 109 struct timeval& start_time) { | 109 struct timeval& start_time) { |
| 110 fd_set readfds, writefds, exceptfds; | 110 fd_set readfds, writefds, exceptfds; |
| 111 struct timeval timeout; | 111 struct timeval timeout; |
| 112 if (*total_timeout != -1) { | 112 int gone = 0; |
| 113 if (total_timeout != -1) { |
| 113 struct timeval time_now; | 114 struct timeval time_now; |
| 114 gettimeofday(&time_now, NULL); | 115 gettimeofday(&time_now, NULL); |
| 115 int seconds = time_now.tv_sec - start_time.tv_sec; | 116 int seconds = time_now.tv_sec - start_time.tv_sec; |
| 116 int gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000; | 117 gone = seconds * 1000 + (time_now.tv_usec - start_time.tv_usec) / 1000; |
| 117 if (gone >= *total_timeout) return false; | 118 if (gone >= total_timeout) return false; |
| 118 *total_timeout -= gone; | |
| 119 } | 119 } |
| 120 FD_ZERO(&readfds); | 120 FD_ZERO(&readfds); |
| 121 FD_ZERO(&writefds); | 121 FD_ZERO(&writefds); |
| 122 FD_ZERO(&exceptfds); | 122 FD_ZERO(&exceptfds); |
| 123 FD_SET(fd, &readfds); | 123 FD_SET(fd, &readfds); |
| 124 FD_SET(fd, &exceptfds); | 124 FD_SET(fd, &exceptfds); |
| 125 if (read_timeout == -1 || | 125 if (read_timeout == -1 || |
| 126 (*total_timeout != -1 && *total_timeout < read_timeout)) { | 126 (total_timeout != -1 && total_timeout - gone < read_timeout)) { |
| 127 read_timeout = *total_timeout; | 127 read_timeout = total_timeout - gone; |
| 128 } | 128 } |
| 129 timeout.tv_usec = (read_timeout % 1000) * 1000; | 129 timeout.tv_usec = (read_timeout % 1000) * 1000; |
| 130 timeout.tv_sec = read_timeout / 1000; | 130 timeout.tv_sec = read_timeout / 1000; |
| 131 int number_of_fds_ready = select(fd + 1, | 131 int number_of_fds_ready = select(fd + 1, |
| 132 &readfds, | 132 &readfds, |
| 133 &writefds, | 133 &writefds, |
| 134 &exceptfds, | 134 &exceptfds, |
| 135 read_timeout != -1 ? &timeout : NULL); | 135 read_timeout != -1 ? &timeout : NULL); |
| 136 return number_of_fds_ready == 1; | 136 return number_of_fds_ready == 1; |
| 137 } | 137 } |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 } | 299 } |
| 300 return true; | 300 return true; |
| 301 } | 301 } |
| 302 | 302 |
| 303 | 303 |
| 304 // Accumulates the output from the child in a string handle. Returns true if it | 304 // Accumulates the output from the child in a string handle. Returns true if it |
| 305 // succeeded or false if an exception was thrown. | 305 // succeeded or false if an exception was thrown. |
| 306 static Handle<Value> GetStdout(int child_fd, | 306 static Handle<Value> GetStdout(int child_fd, |
| 307 struct timeval& start_time, | 307 struct timeval& start_time, |
| 308 int read_timeout, | 308 int read_timeout, |
| 309 int* total_timeout) { | 309 int total_timeout) { |
| 310 Handle<String> accumulator = String::Empty(); | 310 Handle<String> accumulator = String::Empty(); |
| 311 const char* source = "function(a, b) { return a + b; }"; | 311 const char* source = "function(a, b) { return a + b; }"; |
| 312 Handle<Value> cons_as_obj(Script::Compile(String::New(source))->Run()); | 312 Handle<Value> cons_as_obj(Script::Compile(String::New(source))->Run()); |
| 313 Handle<Function> cons_function(Function::Cast(*cons_as_obj)); | 313 Handle<Function> cons_function(Function::Cast(*cons_as_obj)); |
| 314 Handle<Value> cons_args[2]; | 314 Handle<Value> cons_args[2]; |
| 315 | 315 |
| 316 int fullness = 0; | 316 int fullness = 0; |
| 317 static const int kStdoutReadBufferSize = 4096; | 317 static const int kStdoutReadBufferSize = 4096; |
| 318 char buffer[kStdoutReadBufferSize]; | 318 char buffer[kStdoutReadBufferSize]; |
| 319 | 319 |
| 320 if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) { | 320 if (fcntl(child_fd, F_SETFL, O_NONBLOCK) != 0) { |
| 321 return ThrowException(String::New(strerror(errno))); | 321 return ThrowException(String::New(strerror(errno))); |
| 322 } | 322 } |
| 323 | 323 |
| 324 int bytes_read; | 324 int bytes_read; |
| 325 do { | 325 do { |
| 326 bytes_read = read(child_fd, | 326 bytes_read = read(child_fd, |
| 327 buffer + fullness, | 327 buffer + fullness, |
| 328 kStdoutReadBufferSize - fullness); | 328 kStdoutReadBufferSize - fullness); |
| 329 if (bytes_read == -1) { | 329 if (bytes_read == -1) { |
| 330 if (errno == EAGAIN) { | 330 if (errno == EAGAIN) { |
| 331 if (!WaitOnFD(child_fd, | 331 if (!WaitOnFD(child_fd, |
| 332 read_timeout, | 332 read_timeout, |
| 333 total_timeout, | 333 total_timeout, |
| 334 start_time) || | 334 start_time) || |
| 335 (TimeIsOut(start_time, *total_timeout))) { | 335 (TimeIsOut(start_time, total_timeout))) { |
| 336 return ThrowException(String::New("Timed out waiting for output")); | 336 return ThrowException(String::New("Timed out waiting for output")); |
| 337 } | 337 } |
| 338 continue; | 338 continue; |
| 339 } else if (errno == EINTR) { | 339 } else if (errno == EINTR) { |
| 340 continue; | 340 continue; |
| 341 } else { | 341 } else { |
| 342 break; | 342 break; |
| 343 } | 343 } |
| 344 } | 344 } |
| 345 if (bytes_read + fullness > 0) { | 345 if (bytes_read + fullness > 0) { |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 close(exec_error_fds[kWriteFD]); | 495 close(exec_error_fds[kWriteFD]); |
| 496 close(stdout_fds[kWriteFD]); | 496 close(stdout_fds[kWriteFD]); |
| 497 OpenFDCloser error_read_closer(exec_error_fds[kReadFD]); | 497 OpenFDCloser error_read_closer(exec_error_fds[kReadFD]); |
| 498 OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]); | 498 OpenFDCloser stdout_read_closer(stdout_fds[kReadFD]); |
| 499 | 499 |
| 500 if (!ChildLaunchedOK(exec_error_fds)) return v8::Undefined(); | 500 if (!ChildLaunchedOK(exec_error_fds)) return v8::Undefined(); |
| 501 | 501 |
| 502 Handle<Value> accumulator = GetStdout(stdout_fds[kReadFD], | 502 Handle<Value> accumulator = GetStdout(stdout_fds[kReadFD], |
| 503 start_time, | 503 start_time, |
| 504 read_timeout, | 504 read_timeout, |
| 505 &total_timeout); | 505 total_timeout); |
| 506 if (accumulator->IsUndefined()) { | 506 if (accumulator->IsUndefined()) { |
| 507 kill(pid, SIGINT); // On timeout, kill the subprocess. | 507 kill(pid, SIGINT); // On timeout, kill the subprocess. |
| 508 return accumulator; | 508 return accumulator; |
| 509 } | 509 } |
| 510 | 510 |
| 511 if (!WaitForChild(pid, | 511 if (!WaitForChild(pid, |
| 512 child_waiter, | 512 child_waiter, |
| 513 start_time, | 513 start_time, |
| 514 read_timeout, | 514 read_timeout, |
| 515 total_timeout)) { | 515 total_timeout)) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) { | 659 void Shell::AddOSMethods(Handle<ObjectTemplate> os_templ) { |
| 660 os_templ->Set(String::New("system"), FunctionTemplate::New(System)); | 660 os_templ->Set(String::New("system"), FunctionTemplate::New(System)); |
| 661 os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory)); | 661 os_templ->Set(String::New("chdir"), FunctionTemplate::New(ChangeDirectory)); |
| 662 os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment)); | 662 os_templ->Set(String::New("setenv"), FunctionTemplate::New(SetEnvironment)); |
| 663 os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask)); | 663 os_templ->Set(String::New("umask"), FunctionTemplate::New(SetUMask)); |
| 664 os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory)); | 664 os_templ->Set(String::New("mkdirp"), FunctionTemplate::New(MakeDirectory)); |
| 665 os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory)); | 665 os_templ->Set(String::New("rmdir"), FunctionTemplate::New(RemoveDirectory)); |
| 666 } | 666 } |
| 667 | 667 |
| 668 } // namespace v8 | 668 } // namespace v8 |
| OLD | NEW |