| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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(HOST_OS_FUCHSIA) | 8 #if defined(HOST_OS_FUCHSIA) |
| 9 | 9 |
| 10 #include "bin/process.h" | 10 #include "bin/process.h" |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 57 // the pipe used to communicate the exit code of the process to Dart. | 57 // the pipe used to communicate the exit code of the process to Dart. |
| 58 // ProcessInfo objects are kept in the static singly-linked | 58 // ProcessInfo objects are kept in the static singly-linked |
| 59 // ProcessInfoList. | 59 // ProcessInfoList. |
| 60 class ProcessInfo { | 60 class ProcessInfo { |
| 61 public: | 61 public: |
| 62 ProcessInfo(mx_handle_t process, intptr_t fd) | 62 ProcessInfo(mx_handle_t process, intptr_t fd) |
| 63 : process_(process), exit_pipe_fd_(fd) {} | 63 : process_(process), exit_pipe_fd_(fd) {} |
| 64 ~ProcessInfo() { | 64 ~ProcessInfo() { |
| 65 int closed = NO_RETRY_EXPECTED(close(exit_pipe_fd_)); | 65 int closed = NO_RETRY_EXPECTED(close(exit_pipe_fd_)); |
| 66 if (closed != 0) { | 66 if (closed != 0) { |
| 67 FATAL("Failed to close process exit code pipe"); | 67 LOG_ERR("Failed to close process exit code pipe"); |
| 68 } | 68 } |
| 69 mx_handle_close(process_); | 69 mx_handle_close(process_); |
| 70 } | 70 } |
| 71 mx_handle_t process() const { return process_; } | 71 mx_handle_t process() const { return process_; } |
| 72 intptr_t exit_pipe_fd() const { return exit_pipe_fd_; } | 72 intptr_t exit_pipe_fd() const { return exit_pipe_fd_; } |
| 73 ProcessInfo* next() const { return next_; } | 73 ProcessInfo* next() const { return next_; } |
| 74 void set_next(ProcessInfo* info) { next_ = info; } | 74 void set_next(ProcessInfo* info) { next_ = info; } |
| 75 | 75 |
| 76 private: | 76 private: |
| 77 mx_handle_t process_; | 77 mx_handle_t process_; |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 class ExitCodeHandler { | 149 class ExitCodeHandler { |
| 150 public: | 150 public: |
| 151 // Notify the ExitCodeHandler that another process exists. | 151 // Notify the ExitCodeHandler that another process exists. |
| 152 static void Start() { | 152 static void Start() { |
| 153 // Multiple isolates could be starting processes at the same | 153 // Multiple isolates could be starting processes at the same |
| 154 // time. Make sure that only one ExitCodeHandler thread exists. | 154 // time. Make sure that only one ExitCodeHandler thread exists. |
| 155 MonitorLocker locker(monitor_); | 155 MonitorLocker locker(monitor_); |
| 156 if (running_) { | 156 if (running_) { |
| 157 return; | 157 return; |
| 158 } | 158 } |
| 159 | |
| 160 LOG_INFO("ExitCodeHandler Starting\n"); | 159 LOG_INFO("ExitCodeHandler Starting\n"); |
| 161 | 160 |
| 162 mx_status_t status = mx_socket_create(0, &interrupt_in_, &interrupt_out_); | 161 mx_status_t status = mx_port_create(0, &port_); |
| 163 if (status < 0) { | 162 if (status != MX_OK) { |
| 164 FATAL1("Failed to create exit code handler interrupt socket: %s\n", | 163 FATAL1("ExitCodeHandler: mx_port_create failed: %s\n", |
| 165 mx_status_get_string(status)); | 164 mx_status_get_string(status)); |
| 165 return; |
| 166 } | 166 } |
| 167 | 167 |
| 168 // Start thread that handles process exits when wait returns. | 168 // Start thread that handles process exits when wait returns. |
| 169 intptr_t result = | 169 intptr_t result = Thread::Start(ExitCodeHandlerEntry, 0); |
| 170 Thread::Start(ExitCodeHandlerEntry, static_cast<uword>(interrupt_out_)); | |
| 171 if (result != 0) { | 170 if (result != 0) { |
| 172 FATAL1("Failed to start exit code handler worker thread %ld", result); | 171 FATAL1("Failed to start exit code handler worker thread %ld", result); |
| 173 } | 172 } |
| 174 | 173 |
| 175 running_ = true; | 174 running_ = true; |
| 176 } | 175 } |
| 177 | 176 |
| 178 static void Add(mx_handle_t process) { | 177 static mx_status_t Add(mx_handle_t process) { |
| 179 MonitorLocker locker(monitor_); | 178 MonitorLocker locker(monitor_); |
| 180 LOG_INFO("ExitCodeHandler Adding Process: %ld\n", process); | 179 LOG_INFO("ExitCodeHandler Adding Process: %ld\n", process); |
| 181 SendMessage(Message::kAdd, process); | 180 return mx_object_wait_async(process, port_, static_cast<uint64_t>(process), |
| 181 MX_TASK_TERMINATED, MX_WAIT_ASYNC_ONCE); |
| 182 } | 182 } |
| 183 | 183 |
| 184 static void Terminate() { | 184 static void Terminate() { |
| 185 MonitorLocker locker(monitor_); | 185 MonitorLocker locker(monitor_); |
| 186 if (!running_) { | 186 if (!running_) { |
| 187 return; | 187 return; |
| 188 } | 188 } |
| 189 running_ = false; | 189 running_ = false; |
| 190 | 190 |
| 191 LOG_INFO("ExitCodeHandler Terminating\n"); | 191 LOG_INFO("ExitCodeHandler Terminating\n"); |
| 192 SendMessage(Message::kShutdown, MX_HANDLE_INVALID); | 192 SendShutdownMessage(); |
| 193 | 193 |
| 194 while (!terminate_done_) { | 194 while (!terminate_done_) { |
| 195 monitor_->Wait(Monitor::kNoTimeout); | 195 monitor_->Wait(Monitor::kNoTimeout); |
| 196 } | 196 } |
| 197 mx_handle_close(interrupt_in_); | 197 mx_handle_close(port_); |
| 198 LOG_INFO("ExitCodeHandler Terminated\n"); | 198 LOG_INFO("ExitCodeHandler Terminated\n"); |
| 199 } | 199 } |
| 200 | 200 |
| 201 private: | 201 private: |
| 202 class Message { | 202 static const uint64_t kShutdownPacketKey = 1; |
| 203 public: | |
| 204 enum Command { | |
| 205 kAdd, | |
| 206 kShutdown, | |
| 207 }; | |
| 208 Command command; | |
| 209 mx_handle_t handle; | |
| 210 }; | |
| 211 | 203 |
| 212 static void SendMessage(Message::Command command, mx_handle_t handle) { | 204 static void SendShutdownMessage() { |
| 213 Message msg; | 205 mx_port_packet_t pkt; |
| 214 msg.command = command; | 206 pkt.key = kShutdownPacketKey; |
| 215 msg.handle = handle; | 207 mx_status_t status = mx_port_queue(port_, reinterpret_cast<void*>(&pkt), 0); |
| 216 size_t actual; | 208 if (status != MX_OK) { |
| 217 mx_status_t status = | 209 Log::PrintErr("ExitCodeHandler: mx_port_queue failed: %s\n", |
| 218 mx_socket_write(interrupt_in_, 0, &msg, sizeof(msg), &actual); | 210 mx_status_get_string(status)); |
| 219 if (status < 0) { | |
| 220 FATAL1("Write to exit handler interrupt handle failed: %s\n", | |
| 221 mx_status_get_string(status)); | |
| 222 } | 211 } |
| 223 ASSERT(actual == sizeof(msg)); | |
| 224 } | 212 } |
| 225 | 213 |
| 226 // Entry point for the separate exit code handler thread started by | 214 // Entry point for the separate exit code handler thread started by |
| 227 // the ExitCodeHandler. | 215 // the ExitCodeHandler. |
| 228 static void ExitCodeHandlerEntry(uword param) { | 216 static void ExitCodeHandlerEntry(uword param) { |
| 229 LOG_INFO("ExitCodeHandler Entering ExitCodeHandler thread\n"); | 217 LOG_INFO("ExitCodeHandler Entering ExitCodeHandler thread\n"); |
| 230 item_capacity_ = 16; | |
| 231 items_ = reinterpret_cast<mx_wait_item_t*>( | |
| 232 malloc(item_capacity_ * sizeof(*items_))); | |
| 233 items_to_remove_ = reinterpret_cast<intptr_t*>( | |
| 234 malloc(item_capacity_ * sizeof(*items_to_remove_))); | |
| 235 | 218 |
| 236 // The interrupt handle is fixed to the first entry. | 219 mx_port_packet_t pkt; |
| 237 items_[0].handle = interrupt_out_; | 220 while (true) { |
| 238 items_[0].waitfor = MX_SOCKET_READABLE | MX_SOCKET_PEER_CLOSED; | 221 mx_status_t status = mx_port_wait(port_, MX_TIME_INFINITE, |
| 239 items_[0].pending = MX_SIGNAL_NONE; | 222 reinterpret_cast<void*>(&pkt), 0); |
| 240 item_count_ = 1; | 223 if (status != MX_OK) { |
| 241 | 224 FATAL1("ExitCodeHandler: mx_port_wait failed: %s\n", |
| 242 while (!do_shutdown_) { | |
| 243 LOG_INFO("ExitCodeHandler Calling mx_object_wait_many: %ld items\n", | |
| 244 item_count_); | |
| 245 mx_status_t status = | |
| 246 mx_object_wait_many(items_, item_count_, MX_TIME_INFINITE); | |
| 247 if (status < 0) { | |
| 248 FATAL1("Exit code handler handle wait failed: %s\n", | |
| 249 mx_status_get_string(status)); | 225 mx_status_get_string(status)); |
| 250 } | 226 } |
| 251 LOG_INFO("ExitCodeHandler mx_object_wait_many returned\n"); | 227 if (pkt.type == MX_PKT_TYPE_USER) { |
| 252 | 228 ASSERT(pkt.key == kShutdownPacketKey); |
| 253 bool have_interrupt = false; | 229 break; |
| 254 intptr_t remove_count = 0; | |
| 255 for (intptr_t i = 0; i < item_count_; i++) { | |
| 256 if (items_[i].pending == MX_SIGNAL_NONE) { | |
| 257 continue; | |
| 258 } | |
| 259 if (i == 0) { | |
| 260 LOG_INFO("ExitCodeHandler thread saw interrupt\n"); | |
| 261 have_interrupt = true; | |
| 262 continue; | |
| 263 } | |
| 264 ASSERT(items_[i].waitfor == MX_TASK_TERMINATED); | |
| 265 ASSERT((items_[i].pending & MX_TASK_TERMINATED) != 0); | |
| 266 LOG_INFO("ExitCodeHandler signal for %ld\n", items_[i].handle); | |
| 267 SendProcessStatus(items_[i].handle); | |
| 268 items_to_remove_[remove_count++] = i; | |
| 269 } | 230 } |
| 270 for (intptr_t i = 0; i < remove_count; i++) { | 231 mx_handle_t process = static_cast<mx_handle_t>(pkt.key); |
| 271 RemoveItem(items_to_remove_[i]); | 232 mx_signals_t observed = pkt.signal.observed; |
| 233 if ((observed & MX_TASK_TERMINATED) == MX_SIGNAL_NONE) { |
| 234 LOG_ERR("ExitCodeHandler: Unexpected signals, process %ld: %lx\n", |
| 235 process, observed); |
| 272 } | 236 } |
| 273 if (have_interrupt) { | 237 SendProcessStatus(process); |
| 274 HandleInterruptMsg(); | |
| 275 } | |
| 276 } | 238 } |
| 277 | 239 |
| 278 LOG_INFO("ExitCodeHandler thread shutting down\n"); | 240 LOG_INFO("ExitCodeHandler thread shutting down\n"); |
| 279 mx_handle_close(interrupt_out_); | |
| 280 free(items_); | |
| 281 items_ = NULL; | |
| 282 free(items_to_remove_); | |
| 283 items_to_remove_ = NULL; | |
| 284 item_count_ = 0; | |
| 285 item_capacity_ = 0; | |
| 286 | |
| 287 terminate_done_ = true; | 241 terminate_done_ = true; |
| 288 monitor_->Notify(); | 242 monitor_->Notify(); |
| 289 } | 243 } |
| 290 | 244 |
| 291 static void SendProcessStatus(mx_handle_t process) { | 245 static void SendProcessStatus(mx_handle_t process) { |
| 292 LOG_INFO("ExitCodeHandler thread getting process status: %ld\n", process); | 246 LOG_INFO("ExitCodeHandler thread getting process status: %ld\n", process); |
| 247 int return_code = -1; |
| 293 mx_info_process_t proc_info; | 248 mx_info_process_t proc_info; |
| 294 mx_status_t status = mx_object_get_info( | 249 mx_status_t status = mx_object_get_info( |
| 295 process, MX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL); | 250 process, MX_INFO_PROCESS, &proc_info, sizeof(proc_info), NULL, NULL); |
| 296 if (status < 0) { | 251 if (status != MX_OK) { |
| 297 FATAL1("mx_object_get_info failed on process handle: %s\n", | 252 Log::PrintErr("ExitCodeHandler: mx_object_get_info failed: %s\n", |
| 298 mx_status_get_string(status)); | 253 mx_status_get_string(status)); |
| 254 } else { |
| 255 return_code = proc_info.return_code; |
| 299 } | 256 } |
| 300 | 257 mx_handle_close(process); |
| 301 const int return_code = proc_info.return_code; | |
| 302 status = mx_handle_close(process); | |
| 303 if (status < 0) { | |
| 304 FATAL1("Failed to close process handle: %s\n", | |
| 305 mx_status_get_string(status)); | |
| 306 } | |
| 307 LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process, | 258 LOG_INFO("ExitCodeHandler thread process %ld exited with %d\n", process, |
| 308 return_code); | 259 return_code); |
| 309 | 260 |
| 310 const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process); | 261 const intptr_t exit_code_fd = ProcessInfoList::LookupProcessExitFd(process); |
| 311 LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process, | 262 LOG_INFO("ExitCodeHandler thread sending %ld code %d on fd %ld\n", process, |
| 312 return_code, exit_code_fd); | 263 return_code, exit_code_fd); |
| 313 if (exit_code_fd != 0) { | 264 if (exit_code_fd != 0) { |
| 314 int exit_message[2]; | 265 int exit_message[2]; |
| 315 exit_message[0] = abs(return_code); | 266 exit_message[0] = abs(return_code); |
| 316 exit_message[1] = return_code >= 0 ? 0 : 1; | 267 exit_message[1] = return_code >= 0 ? 0 : 1; |
| 317 intptr_t result = FDUtils::WriteToBlocking(exit_code_fd, &exit_message, | 268 intptr_t result = FDUtils::WriteToBlocking(exit_code_fd, &exit_message, |
| 318 sizeof(exit_message)); | 269 sizeof(exit_message)); |
| 319 ASSERT((result == -1) || (result == sizeof(exit_code_fd))); | 270 ASSERT((result == -1) || (result == sizeof(exit_code_fd))); |
| 320 if ((result == -1) && (errno != EPIPE)) { | 271 if ((result == -1) && (errno != EPIPE)) { |
| 321 int err = errno; | 272 int err = errno; |
| 322 FATAL1("Failed to write exit code to pipe: %d\n", err); | 273 Log::PrintErr("Failed to write exit code for process %ld: errno=%d\n", |
| 274 process, err); |
| 323 } | 275 } |
| 324 LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result, | 276 LOG_INFO("ExitCodeHandler thread wrote %ld bytes to fd %ld\n", result, |
| 325 exit_code_fd); | 277 exit_code_fd); |
| 326 LOG_INFO("ExitCodeHandler thread removing process %ld from list\n", | 278 LOG_INFO("ExitCodeHandler thread removing process %ld from list\n", |
| 327 process); | 279 process); |
| 328 ProcessInfoList::RemoveProcess(process); | 280 ProcessInfoList::RemoveProcess(process); |
| 281 } else { |
| 282 LOG_ERR("ExitCodeHandler: Process %ld not found\n", process); |
| 329 } | 283 } |
| 330 } | 284 } |
| 331 | 285 |
| 332 static void HandleInterruptMsg() { | 286 static mx_handle_t port_; |
| 333 ASSERT(items_[0].handle == interrupt_out_); | |
| 334 ASSERT(items_[0].waitfor == MX_SOCKET_READABLE); | |
| 335 ASSERT((items_[0].pending & MX_SOCKET_READABLE) != 0); | |
| 336 while (true) { | |
| 337 Message msg; | |
| 338 size_t actual = 0; | |
| 339 LOG_INFO("ExitCodeHandler thread reading interrupt message\n"); | |
| 340 mx_status_t status = | |
| 341 mx_socket_read(interrupt_out_, 0, &msg, sizeof(msg), &actual); | |
| 342 if (status == MX_ERR_SHOULD_WAIT) { | |
| 343 LOG_INFO("ExitCodeHandler thread done reading interrupt messages\n"); | |
| 344 return; | |
| 345 } | |
| 346 if (status < 0) { | |
| 347 FATAL1("Failed to read exit handler interrupt handle: %s\n", | |
| 348 mx_status_get_string(status)); | |
| 349 } | |
| 350 if (actual < sizeof(msg)) { | |
| 351 FATAL1("Short read from exit handler interrupt handle: %ld\n", actual); | |
| 352 } | |
| 353 switch (msg.command) { | |
| 354 case Message::kShutdown: | |
| 355 LOG_INFO("ExitCodeHandler thread got shutdown message\n"); | |
| 356 do_shutdown_ = true; | |
| 357 break; | |
| 358 case Message::kAdd: | |
| 359 LOG_INFO("ExitCodeHandler thread got add message: %ld\n", msg.handle); | |
| 360 AddItem(msg.handle); | |
| 361 break; | |
| 362 } | |
| 363 } | |
| 364 } | |
| 365 | |
| 366 static void AddItem(mx_handle_t h) { | |
| 367 if (item_count_ == item_capacity_) { | |
| 368 item_capacity_ = item_capacity_ + (item_capacity_ >> 1); | |
| 369 items_ = | |
| 370 reinterpret_cast<mx_wait_item_t*>(realloc(items_, item_capacity_)); | |
| 371 items_to_remove_ = reinterpret_cast<intptr_t*>( | |
| 372 realloc(items_to_remove_, item_capacity_)); | |
| 373 } | |
| 374 LOG_INFO("ExitCodeHandler thread adding item %ld at %ld\n", h, item_count_); | |
| 375 items_[item_count_].handle = h; | |
| 376 items_[item_count_].waitfor = MX_TASK_TERMINATED; | |
| 377 items_[item_count_].pending = MX_SIGNAL_NONE; | |
| 378 item_count_++; | |
| 379 } | |
| 380 | |
| 381 static void RemoveItem(intptr_t idx) { | |
| 382 LOG_INFO("ExitCodeHandler thread removing item %ld at %ld\n", | |
| 383 items_[idx].handle, idx); | |
| 384 ASSERT(idx != 0); | |
| 385 const intptr_t last = item_count_ - 1; | |
| 386 items_[idx].handle = MX_HANDLE_INVALID; | |
| 387 items_[idx].waitfor = MX_SIGNAL_NONE; | |
| 388 items_[idx].pending = MX_SIGNAL_NONE; | |
| 389 if (idx != last) { | |
| 390 items_[idx] = items_[last]; | |
| 391 } | |
| 392 item_count_--; | |
| 393 } | |
| 394 | |
| 395 // Interrupt channel. | |
| 396 static mx_handle_t interrupt_in_; | |
| 397 static mx_handle_t interrupt_out_; | |
| 398 | |
| 399 // Accessed only by the ExitCodeHandler thread. | |
| 400 static mx_wait_item_t* items_; | |
| 401 static intptr_t* items_to_remove_; | |
| 402 static intptr_t item_count_; | |
| 403 static intptr_t item_capacity_; | |
| 404 | 287 |
| 405 // Protected by monitor_. | 288 // Protected by monitor_. |
| 406 static bool do_shutdown_; | |
| 407 static bool terminate_done_; | 289 static bool terminate_done_; |
| 408 static bool running_; | 290 static bool running_; |
| 409 static Monitor* monitor_; | 291 static Monitor* monitor_; |
| 410 | 292 |
| 411 DISALLOW_ALLOCATION(); | 293 DISALLOW_ALLOCATION(); |
| 412 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); | 294 DISALLOW_IMPLICIT_CONSTRUCTORS(ExitCodeHandler); |
| 413 }; | 295 }; |
| 414 | 296 |
| 415 mx_handle_t ExitCodeHandler::interrupt_in_ = MX_HANDLE_INVALID; | 297 mx_handle_t ExitCodeHandler::port_ = MX_HANDLE_INVALID; |
| 416 mx_handle_t ExitCodeHandler::interrupt_out_ = MX_HANDLE_INVALID; | |
| 417 mx_wait_item_t* ExitCodeHandler::items_ = NULL; | |
| 418 intptr_t* ExitCodeHandler::items_to_remove_ = NULL; | |
| 419 intptr_t ExitCodeHandler::item_count_ = 0; | |
| 420 intptr_t ExitCodeHandler::item_capacity_ = 0; | |
| 421 | |
| 422 bool ExitCodeHandler::do_shutdown_ = false; | |
| 423 bool ExitCodeHandler::running_ = false; | 298 bool ExitCodeHandler::running_ = false; |
| 424 bool ExitCodeHandler::terminate_done_ = false; | 299 bool ExitCodeHandler::terminate_done_ = false; |
| 425 Monitor* ExitCodeHandler::monitor_ = new Monitor(); | 300 Monitor* ExitCodeHandler::monitor_ = new Monitor(); |
| 426 | 301 |
| 427 void Process::TerminateExitCodeHandler() { | 302 void Process::TerminateExitCodeHandler() { |
| 428 ExitCodeHandler::Terminate(); | 303 ExitCodeHandler::Terminate(); |
| 429 } | 304 } |
| 430 | 305 |
| 431 intptr_t Process::CurrentProcessId() { | 306 intptr_t Process::CurrentProcessId() { |
| 432 return static_cast<intptr_t>(getpid()); | 307 return static_cast<intptr_t>(getpid()); |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 718 return status; | 593 return status; |
| 719 } | 594 } |
| 720 ASSERT(lp != NULL); | 595 ASSERT(lp != NULL); |
| 721 | 596 |
| 722 // Launch it. | 597 // Launch it. |
| 723 LOG_INFO("ProcessStarter: Start() Calling launchpad_start\n"); | 598 LOG_INFO("ProcessStarter: Start() Calling launchpad_start\n"); |
| 724 mx_handle_t process = MX_HANDLE_INVALID; | 599 mx_handle_t process = MX_HANDLE_INVALID; |
| 725 const char* errormsg = NULL; | 600 const char* errormsg = NULL; |
| 726 status = launchpad_go(lp, &process, &errormsg); | 601 status = launchpad_go(lp, &process, &errormsg); |
| 727 lp = NULL; // launchpad_go() calls launchpad_destroy() on the launchpad. | 602 lp = NULL; // launchpad_go() calls launchpad_destroy() on the launchpad. |
| 728 if (status < 0) { | 603 if (status != MX_OK) { |
| 729 LOG_INFO("ProcessStarter: Start() launchpad_start failed\n"); | 604 LOG_ERR("ProcessStarter: Start() launchpad_start failed\n"); |
| 730 const intptr_t kMaxMessageSize = 256; | |
| 731 close(exit_pipe_fds[0]); | 605 close(exit_pipe_fds[0]); |
| 732 close(exit_pipe_fds[1]); | 606 close(exit_pipe_fds[1]); |
| 733 char* message = DartUtils::ScopedCString(kMaxMessageSize); | 607 ReportStartError(errormsg); |
| 734 snprintf(message, kMaxMessageSize, "%s:%d: launchpad_start failed: %s\n", | |
| 735 __FILE__, __LINE__, errormsg); | |
| 736 *os_error_message_ = message; | |
| 737 return status; | 608 return status; |
| 738 } | 609 } |
| 739 | 610 |
| 740 LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n", | 611 LOG_INFO("ProcessStarter: Start() adding %ld to list with exit_pipe %d\n", |
| 741 process, exit_pipe_fds[1]); | 612 process, exit_pipe_fds[1]); |
| 742 ProcessInfoList::AddProcess(process, exit_pipe_fds[1]); | 613 ProcessInfoList::AddProcess(process, exit_pipe_fds[1]); |
| 743 ExitCodeHandler::Start(); | 614 ExitCodeHandler::Start(); |
| 744 ExitCodeHandler::Add(process); | 615 status = ExitCodeHandler::Add(process); |
| 616 if (status != MX_OK) { |
| 617 LOG_ERR("ProcessStarter: ExitCodeHandler: Add failed: %s\n", |
| 618 mx_status_get_string(status)); |
| 619 close(exit_pipe_fds[0]); |
| 620 close(exit_pipe_fds[1]); |
| 621 mx_task_kill(process); |
| 622 ProcessInfoList::RemoveProcess(process); |
| 623 ReportStartError(mx_status_get_string(status)); |
| 624 return status; |
| 625 } |
| 745 | 626 |
| 746 // The IOHandles allocated below are returned to Dart code. The Dart code | 627 // The IOHandles allocated below are returned to Dart code. The Dart code |
| 747 // calls into the runtime again to allocate a C++ Socket object, which | 628 // calls into the runtime again to allocate a C++ Socket object, which |
| 748 // becomes the native field of a Dart _NativeSocket object. The C++ Socket | 629 // becomes the native field of a Dart _NativeSocket object. The C++ Socket |
| 749 // object and the EventHandler manage the lifetime of these IOHandles. | 630 // object and the EventHandler manage the lifetime of these IOHandles. |
| 750 *id_ = process; | 631 *id_ = process; |
| 751 FDUtils::SetNonBlocking(read_in_); | 632 FDUtils::SetNonBlocking(read_in_); |
| 752 *in_ = reinterpret_cast<intptr_t>(new IOHandle(read_in_)); | 633 *in_ = reinterpret_cast<intptr_t>(new IOHandle(read_in_)); |
| 753 read_in_ = -1; | 634 read_in_ = -1; |
| 754 FDUtils::SetNonBlocking(read_err_); | 635 FDUtils::SetNonBlocking(read_err_); |
| 755 *err_ = reinterpret_cast<intptr_t>(new IOHandle(read_err_)); | 636 *err_ = reinterpret_cast<intptr_t>(new IOHandle(read_err_)); |
| 756 read_err_ = -1; | 637 read_err_ = -1; |
| 757 FDUtils::SetNonBlocking(write_out_); | 638 FDUtils::SetNonBlocking(write_out_); |
| 758 *out_ = reinterpret_cast<intptr_t>(new IOHandle(write_out_)); | 639 *out_ = reinterpret_cast<intptr_t>(new IOHandle(write_out_)); |
| 759 write_out_ = -1; | 640 write_out_ = -1; |
| 760 FDUtils::SetNonBlocking(exit_pipe_fds[0]); | 641 FDUtils::SetNonBlocking(exit_pipe_fds[0]); |
| 761 *exit_event_ = reinterpret_cast<intptr_t>(new IOHandle(exit_pipe_fds[0])); | 642 *exit_event_ = reinterpret_cast<intptr_t>(new IOHandle(exit_pipe_fds[0])); |
| 762 return 0; | 643 return 0; |
| 763 } | 644 } |
| 764 | 645 |
| 765 private: | 646 private: |
| 647 void ReportStartError(const char* errormsg) { |
| 648 const intptr_t kMaxMessageSize = 256; |
| 649 char* message = DartUtils::ScopedCString(kMaxMessageSize); |
| 650 snprintf(message, kMaxMessageSize, "Process start failed: %s\n", errormsg); |
| 651 *os_error_message_ = message; |
| 652 } |
| 653 |
| 766 mx_status_t SetupLaunchpad(launchpad_t** launchpad) { | 654 mx_status_t SetupLaunchpad(launchpad_t** launchpad) { |
| 767 // TODO(zra): Use the supplied working directory when launchpad adds an | 655 // TODO(zra): Use the supplied working directory when launchpad adds an |
| 768 // API to set it. | 656 // API to set it. |
| 769 ASSERT(launchpad != NULL); | 657 ASSERT(launchpad != NULL); |
| 770 launchpad_t* lp = NULL; | 658 launchpad_t* lp = NULL; |
| 771 launchpad_create(MX_HANDLE_INVALID, program_arguments_[0], &lp); | 659 launchpad_create(MX_HANDLE_INVALID, program_arguments_[0], &lp); |
| 772 launchpad_set_args(lp, program_arguments_count_, program_arguments_); | 660 launchpad_set_args(lp, program_arguments_count_, program_arguments_); |
| 773 launchpad_set_environ(lp, program_environment_); | 661 launchpad_set_environ(lp, program_environment_); |
| 774 launchpad_clone(lp, LP_CLONE_MXIO_NAMESPACE); | 662 launchpad_clone(lp, LP_CLONE_MXIO_NAMESPACE); |
| 775 launchpad_clone(lp, LP_CLONE_MXIO_CWD); | 663 launchpad_clone(lp, LP_CLONE_MXIO_CWD); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 847 } | 735 } |
| 848 | 736 |
| 849 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) {} | 737 void Process::ClearSignalHandler(intptr_t signal, Dart_Port port) {} |
| 850 | 738 |
| 851 } // namespace bin | 739 } // namespace bin |
| 852 } // namespace dart | 740 } // namespace dart |
| 853 | 741 |
| 854 #endif // defined(HOST_OS_FUCHSIA) | 742 #endif // defined(HOST_OS_FUCHSIA) |
| 855 | 743 |
| 856 #endif // !defined(DART_IO_DISABLED) | 744 #endif // !defined(DART_IO_DISABLED) |
| OLD | NEW |