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 |