| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/zygote/zygote_linux.h" | 5 #include "content/zygote/zygote_linux.h" |
| 6 | 6 |
| 7 #include <fcntl.h> | 7 #include <fcntl.h> |
| 8 #include <string.h> | 8 #include <string.h> |
| 9 #include <sys/socket.h> | 9 #include <sys/socket.h> |
| 10 #include <sys/types.h> | 10 #include <sys/types.h> |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 } | 187 } |
| 188 _exit(0); | 188 _exit(0); |
| 189 return false; | 189 return false; |
| 190 } | 190 } |
| 191 | 191 |
| 192 if (len == -1) { | 192 if (len == -1) { |
| 193 PLOG(ERROR) << "Error reading message from browser"; | 193 PLOG(ERROR) << "Error reading message from browser"; |
| 194 return false; | 194 return false; |
| 195 } | 195 } |
| 196 | 196 |
| 197 Pickle pickle(buf, len); | 197 base::Pickle pickle(buf, len); |
| 198 PickleIterator iter(pickle); | 198 base::PickleIterator iter(pickle); |
| 199 | 199 |
| 200 int kind; | 200 int kind; |
| 201 if (iter.ReadInt(&kind)) { | 201 if (iter.ReadInt(&kind)) { |
| 202 switch (kind) { | 202 switch (kind) { |
| 203 case kZygoteCommandFork: | 203 case kZygoteCommandFork: |
| 204 // This function call can return multiple times, once per fork(). | 204 // This function call can return multiple times, once per fork(). |
| 205 return HandleForkRequest(fd, iter, fds.Pass()); | 205 return HandleForkRequest(fd, iter, fds.Pass()); |
| 206 | 206 |
| 207 case kZygoteCommandReap: | 207 case kZygoteCommandReap: |
| 208 if (!fds.empty()) | 208 if (!fds.empty()) |
| (...skipping 19 matching lines...) Expand all Loading... |
| 228 NOTREACHED(); | 228 NOTREACHED(); |
| 229 break; | 229 break; |
| 230 } | 230 } |
| 231 } | 231 } |
| 232 | 232 |
| 233 LOG(WARNING) << "Error parsing message from browser"; | 233 LOG(WARNING) << "Error parsing message from browser"; |
| 234 return false; | 234 return false; |
| 235 } | 235 } |
| 236 | 236 |
| 237 // TODO(jln): remove callers to this broken API. See crbug.com/274855. | 237 // TODO(jln): remove callers to this broken API. See crbug.com/274855. |
| 238 void Zygote::HandleReapRequest(int fd, | 238 void Zygote::HandleReapRequest(int fd, base::PickleIterator iter) { |
| 239 PickleIterator iter) { | |
| 240 base::ProcessId child; | 239 base::ProcessId child; |
| 241 | 240 |
| 242 if (!iter.ReadInt(&child)) { | 241 if (!iter.ReadInt(&child)) { |
| 243 LOG(WARNING) << "Error parsing reap request from browser"; | 242 LOG(WARNING) << "Error parsing reap request from browser"; |
| 244 return; | 243 return; |
| 245 } | 244 } |
| 246 | 245 |
| 247 ZygoteProcessInfo child_info; | 246 ZygoteProcessInfo child_info; |
| 248 if (!GetProcessInfo(child, &child_info)) { | 247 if (!GetProcessInfo(child, &child_info)) { |
| 249 LOG(ERROR) << "Child not found!"; | 248 LOG(ERROR) << "Child not found!"; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 process_info_map_.erase(real_pid); | 315 process_info_map_.erase(real_pid); |
| 317 } | 316 } |
| 318 | 317 |
| 319 if (WIFEXITED(*exit_code) && WEXITSTATUS(*exit_code) == kKilledExitCode) { | 318 if (WIFEXITED(*exit_code) && WEXITSTATUS(*exit_code) == kKilledExitCode) { |
| 320 *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED; | 319 *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED; |
| 321 } | 320 } |
| 322 | 321 |
| 323 return true; | 322 return true; |
| 324 } | 323 } |
| 325 | 324 |
| 326 void Zygote::HandleGetTerminationStatus(int fd, | 325 void Zygote::HandleGetTerminationStatus(int fd, base::PickleIterator iter) { |
| 327 PickleIterator iter) { | |
| 328 bool known_dead; | 326 bool known_dead; |
| 329 base::ProcessHandle child_requested; | 327 base::ProcessHandle child_requested; |
| 330 | 328 |
| 331 if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) { | 329 if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) { |
| 332 LOG(WARNING) << "Error parsing GetTerminationStatus request " | 330 LOG(WARNING) << "Error parsing GetTerminationStatus request " |
| 333 << "from browser"; | 331 << "from browser"; |
| 334 return; | 332 return; |
| 335 } | 333 } |
| 336 | 334 |
| 337 base::TerminationStatus status; | 335 base::TerminationStatus status; |
| 338 int exit_code; | 336 int exit_code; |
| 339 | 337 |
| 340 bool got_termination_status = | 338 bool got_termination_status = |
| 341 GetTerminationStatus(child_requested, known_dead, &status, &exit_code); | 339 GetTerminationStatus(child_requested, known_dead, &status, &exit_code); |
| 342 if (!got_termination_status) { | 340 if (!got_termination_status) { |
| 343 // Assume that if we can't find the child in the sandbox, then | 341 // Assume that if we can't find the child in the sandbox, then |
| 344 // it terminated normally. | 342 // it terminated normally. |
| 345 NOTREACHED(); | 343 NOTREACHED(); |
| 346 status = base::TERMINATION_STATUS_NORMAL_TERMINATION; | 344 status = base::TERMINATION_STATUS_NORMAL_TERMINATION; |
| 347 exit_code = RESULT_CODE_NORMAL_EXIT; | 345 exit_code = RESULT_CODE_NORMAL_EXIT; |
| 348 } | 346 } |
| 349 | 347 |
| 350 Pickle write_pickle; | 348 base::Pickle write_pickle; |
| 351 write_pickle.WriteInt(static_cast<int>(status)); | 349 write_pickle.WriteInt(static_cast<int>(status)); |
| 352 write_pickle.WriteInt(exit_code); | 350 write_pickle.WriteInt(exit_code); |
| 353 ssize_t written = | 351 ssize_t written = |
| 354 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); | 352 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); |
| 355 if (written != static_cast<ssize_t>(write_pickle.size())) | 353 if (written != static_cast<ssize_t>(write_pickle.size())) |
| 356 PLOG(ERROR) << "write"; | 354 PLOG(ERROR) << "write"; |
| 357 } | 355 } |
| 358 | 356 |
| 359 int Zygote::ForkWithRealPid(const std::string& process_type, | 357 int Zygote::ForkWithRealPid(const std::string& process_type, |
| 360 const base::GlobalDescriptors::Mapping& fd_mapping, | 358 const base::GlobalDescriptors::Mapping& fd_mapping, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 453 // be invalid (see below). | 451 // be invalid (see below). |
| 454 base::ProcessId real_pid; | 452 base::ProcessId real_pid; |
| 455 { | 453 { |
| 456 ScopedVector<base::ScopedFD> recv_fds; | 454 ScopedVector<base::ScopedFD> recv_fds; |
| 457 char buf[kZygoteMaxMessageLength]; | 455 char buf[kZygoteMaxMessageLength]; |
| 458 const ssize_t len = UnixDomainSocket::RecvMsg( | 456 const ssize_t len = UnixDomainSocket::RecvMsg( |
| 459 kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds); | 457 kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds); |
| 460 CHECK_GT(len, 0); | 458 CHECK_GT(len, 0); |
| 461 CHECK(recv_fds.empty()); | 459 CHECK(recv_fds.empty()); |
| 462 | 460 |
| 463 Pickle pickle(buf, len); | 461 base::Pickle pickle(buf, len); |
| 464 PickleIterator iter(pickle); | 462 base::PickleIterator iter(pickle); |
| 465 | 463 |
| 466 int kind; | 464 int kind; |
| 467 CHECK(iter.ReadInt(&kind)); | 465 CHECK(iter.ReadInt(&kind)); |
| 468 CHECK(kind == kZygoteCommandForkRealPID); | 466 CHECK(kind == kZygoteCommandForkRealPID); |
| 469 CHECK(iter.ReadInt(&real_pid)); | 467 CHECK(iter.ReadInt(&real_pid)); |
| 470 } | 468 } |
| 471 | 469 |
| 472 // Fork failed. | 470 // Fork failed. |
| 473 if (pid < 0) { | 471 if (pid < 0) { |
| 474 return -1; | 472 return -1; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 495 if (process_info_map_.find(real_pid) != process_info_map_.end()) { | 493 if (process_info_map_.find(real_pid) != process_info_map_.end()) { |
| 496 LOG(ERROR) << "Already tracking PID " << real_pid; | 494 LOG(ERROR) << "Already tracking PID " << real_pid; |
| 497 NOTREACHED(); | 495 NOTREACHED(); |
| 498 } | 496 } |
| 499 process_info_map_[real_pid].internal_pid = pid; | 497 process_info_map_[real_pid].internal_pid = pid; |
| 500 process_info_map_[real_pid].started_from_helper = helper; | 498 process_info_map_[real_pid].started_from_helper = helper; |
| 501 | 499 |
| 502 return real_pid; | 500 return real_pid; |
| 503 } | 501 } |
| 504 | 502 |
| 505 base::ProcessId Zygote::ReadArgsAndFork(PickleIterator iter, | 503 base::ProcessId Zygote::ReadArgsAndFork(base::PickleIterator iter, |
| 506 ScopedVector<base::ScopedFD> fds, | 504 ScopedVector<base::ScopedFD> fds, |
| 507 std::string* uma_name, | 505 std::string* uma_name, |
| 508 int* uma_sample, | 506 int* uma_sample, |
| 509 int* uma_boundary_value) { | 507 int* uma_boundary_value) { |
| 510 std::vector<std::string> args; | 508 std::vector<std::string> args; |
| 511 int argc = 0; | 509 int argc = 0; |
| 512 int numfds = 0; | 510 int numfds = 0; |
| 513 base::GlobalDescriptors::Mapping mapping; | 511 base::GlobalDescriptors::Mapping mapping; |
| 514 std::string process_type; | 512 std::string process_type; |
| 515 std::string channel_id; | 513 std::string channel_id; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 // (we don't have the original argv at this point). | 579 // (we don't have the original argv at this point). |
| 582 SetProcessTitleFromCommandLine(NULL); | 580 SetProcessTitleFromCommandLine(NULL); |
| 583 } else if (child_pid < 0) { | 581 } else if (child_pid < 0) { |
| 584 LOG(ERROR) << "Zygote could not fork: process_type " << process_type | 582 LOG(ERROR) << "Zygote could not fork: process_type " << process_type |
| 585 << " numfds " << numfds << " child_pid " << child_pid; | 583 << " numfds " << numfds << " child_pid " << child_pid; |
| 586 } | 584 } |
| 587 return child_pid; | 585 return child_pid; |
| 588 } | 586 } |
| 589 | 587 |
| 590 bool Zygote::HandleForkRequest(int fd, | 588 bool Zygote::HandleForkRequest(int fd, |
| 591 PickleIterator iter, | 589 base::PickleIterator iter, |
| 592 ScopedVector<base::ScopedFD> fds) { | 590 ScopedVector<base::ScopedFD> fds) { |
| 593 std::string uma_name; | 591 std::string uma_name; |
| 594 int uma_sample; | 592 int uma_sample; |
| 595 int uma_boundary_value; | 593 int uma_boundary_value; |
| 596 base::ProcessId child_pid = ReadArgsAndFork( | 594 base::ProcessId child_pid = ReadArgsAndFork( |
| 597 iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value); | 595 iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value); |
| 598 if (child_pid == 0) | 596 if (child_pid == 0) |
| 599 return true; | 597 return true; |
| 600 // If there's no UMA report for this particular fork, then check if any | 598 // If there's no UMA report for this particular fork, then check if any |
| 601 // helpers have an initial UMA report for us to send instead. | 599 // helpers have an initial UMA report for us to send instead. |
| 602 while (uma_name.empty() && initial_uma_index_ < helpers_.size()) { | 600 while (uma_name.empty() && initial_uma_index_ < helpers_.size()) { |
| 603 helpers_[initial_uma_index_++]->InitialUMA( | 601 helpers_[initial_uma_index_++]->InitialUMA( |
| 604 &uma_name, &uma_sample, &uma_boundary_value); | 602 &uma_name, &uma_sample, &uma_boundary_value); |
| 605 } | 603 } |
| 606 // Must always send reply, as ZygoteHost blocks while waiting for it. | 604 // Must always send reply, as ZygoteHost blocks while waiting for it. |
| 607 Pickle reply_pickle; | 605 base::Pickle reply_pickle; |
| 608 reply_pickle.WriteInt(child_pid); | 606 reply_pickle.WriteInt(child_pid); |
| 609 reply_pickle.WriteString(uma_name); | 607 reply_pickle.WriteString(uma_name); |
| 610 if (!uma_name.empty()) { | 608 if (!uma_name.empty()) { |
| 611 reply_pickle.WriteInt(uma_sample); | 609 reply_pickle.WriteInt(uma_sample); |
| 612 reply_pickle.WriteInt(uma_boundary_value); | 610 reply_pickle.WriteInt(uma_boundary_value); |
| 613 } | 611 } |
| 614 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) != | 612 if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) != |
| 615 static_cast<ssize_t> (reply_pickle.size())) | 613 static_cast<ssize_t> (reply_pickle.size())) |
| 616 PLOG(ERROR) << "write"; | 614 PLOG(ERROR) << "write"; |
| 617 return false; | 615 return false; |
| 618 } | 616 } |
| 619 | 617 |
| 620 bool Zygote::HandleGetSandboxStatus(int fd, | 618 bool Zygote::HandleGetSandboxStatus(int fd, base::PickleIterator iter) { |
| 621 PickleIterator iter) { | |
| 622 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != | 619 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != |
| 623 sizeof(sandbox_flags_)) { | 620 sizeof(sandbox_flags_)) { |
| 624 PLOG(ERROR) << "write"; | 621 PLOG(ERROR) << "write"; |
| 625 } | 622 } |
| 626 | 623 |
| 627 return false; | 624 return false; |
| 628 } | 625 } |
| 629 | 626 |
| 630 } // namespace content | 627 } // namespace content |
| OLD | NEW |