Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1146)

Side by Side Diff: content/zygote/zygote_linux.cc

Issue 1508213002: Replace ScopedVector<ScopedFD> with std::vector<ScopedFD> (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: danakj feedback Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/zygote/zygote_linux.h ('k') | extensions/shell/app/shell_main_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <poll.h> 9 #include <poll.h>
10 #include <signal.h> 10 #include <signal.h>
11 #include <stdint.h> 11 #include <stdint.h>
12 #include <string.h> 12 #include <string.h>
13 #include <sys/socket.h> 13 #include <sys/socket.h>
14 #include <sys/types.h> 14 #include <sys/types.h>
15 #include <sys/wait.h> 15 #include <sys/wait.h>
16
16 #include <utility> 17 #include <utility>
17 18
18 #include "base/command_line.h" 19 #include "base/command_line.h"
19 #include "base/files/file_util.h" 20 #include "base/files/file_util.h"
20 #include "base/linux_util.h" 21 #include "base/linux_util.h"
21 #include "base/logging.h" 22 #include "base/logging.h"
22 #include "base/macros.h" 23 #include "base/macros.h"
23 #include "base/memory/scoped_vector.h"
24 #include "base/pickle.h" 24 #include "base/pickle.h"
25 #include "base/posix/eintr_wrapper.h" 25 #include "base/posix/eintr_wrapper.h"
26 #include "base/posix/global_descriptors.h" 26 #include "base/posix/global_descriptors.h"
27 #include "base/posix/unix_domain_socket_linux.h" 27 #include "base/posix/unix_domain_socket_linux.h"
28 #include "base/process/kill.h" 28 #include "base/process/kill.h"
29 #include "base/process/launch.h" 29 #include "base/process/launch.h"
30 #include "base/process/process.h" 30 #include "base/process/process.h"
31 #include "base/process/process_handle.h" 31 #include "base/process/process_handle.h"
32 #include "base/time/time.h" 32 #include "base/time/time.h"
33 #include "base/trace_event/trace_event.h" 33 #include "base/trace_event/trace_event.h"
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 222
223 bool Zygote::UsingSUIDSandbox() const { 223 bool Zygote::UsingSUIDSandbox() const {
224 return sandbox_flags_ & kSandboxLinuxSUID; 224 return sandbox_flags_ & kSandboxLinuxSUID;
225 } 225 }
226 226
227 bool Zygote::UsingNSSandbox() const { 227 bool Zygote::UsingNSSandbox() const {
228 return sandbox_flags_ & kSandboxLinuxUserNS; 228 return sandbox_flags_ & kSandboxLinuxUserNS;
229 } 229 }
230 230
231 bool Zygote::HandleRequestFromBrowser(int fd) { 231 bool Zygote::HandleRequestFromBrowser(int fd) {
232 ScopedVector<base::ScopedFD> fds; 232 std::vector<base::ScopedFD> fds;
233 char buf[kZygoteMaxMessageLength]; 233 char buf[kZygoteMaxMessageLength];
234 const ssize_t len = base::UnixDomainSocket::RecvMsg( 234 const ssize_t len = base::UnixDomainSocket::RecvMsg(
235 fd, buf, sizeof(buf), &fds); 235 fd, buf, sizeof(buf), &fds);
236 236
237 if (len == 0 || (len == -1 && errno == ECONNRESET)) { 237 if (len == 0 || (len == -1 && errno == ECONNRESET)) {
238 // EOF from the browser. We should die. 238 // EOF from the browser. We should die.
239 // TODO(earthdok): call __sanititizer_cov_dump() here to obtain code 239 // TODO(earthdok): call __sanititizer_cov_dump() here to obtain code
240 // coverage for the Zygote. Currently it's not possible because of 240 // coverage for the Zygote. Currently it's not possible because of
241 // confusion over who is responsible for closing the file descriptor. 241 // confusion over who is responsible for closing the file descriptor.
242 for (std::vector<int>::iterator it = extra_fds_.begin(); 242 for (int fd : extra_fds_) {
243 it < extra_fds_.end(); ++it) { 243 PCHECK(0 == IGNORE_EINTR(close(fd)));
244 PCHECK(0 == IGNORE_EINTR(close(*it)));
245 } 244 }
246 #if !defined(SANITIZER_COVERAGE) 245 #if !defined(SANITIZER_COVERAGE)
247 // TODO(earthdok): add watchdog thread before using this in builds not 246 // TODO(earthdok): add watchdog thread before using this in builds not
248 // using sanitizer coverage. 247 // using sanitizer coverage.
249 CHECK(extra_children_.empty()); 248 CHECK(extra_children_.empty());
250 #endif 249 #endif
251 for (std::vector<base::ProcessHandle>::iterator it = 250 for (base::ProcessHandle pid : extra_children_) {
252 extra_children_.begin(); 251 PCHECK(pid == HANDLE_EINTR(waitpid(pid, NULL, 0)));
253 it < extra_children_.end(); ++it) {
254 PCHECK(*it == HANDLE_EINTR(waitpid(*it, NULL, 0)));
255 } 252 }
256 _exit(0); 253 _exit(0);
257 return false; 254 return false;
258 } 255 }
259 256
260 if (len == -1) { 257 if (len == -1) {
261 PLOG(ERROR) << "Error reading message from browser"; 258 PLOG(ERROR) << "Error reading message from browser";
262 return false; 259 return false;
263 } 260 }
264 261
265 base::Pickle pickle(buf, len); 262 base::Pickle pickle(buf, len);
266 base::PickleIterator iter(pickle); 263 base::PickleIterator iter(pickle);
267 264
268 int kind; 265 int kind;
269 if (iter.ReadInt(&kind)) { 266 if (iter.ReadInt(&kind)) {
270 switch (kind) { 267 switch (kind) {
271 case kZygoteCommandFork: 268 case kZygoteCommandFork:
272 // This function call can return multiple times, once per fork(). 269 // This function call can return multiple times, once per fork().
273 return HandleForkRequest(fd, iter, fds.Pass()); 270 return HandleForkRequest(fd, iter, std::move(fds));
274 271
275 case kZygoteCommandReap: 272 case kZygoteCommandReap:
276 if (!fds.empty()) 273 if (!fds.empty())
277 break; 274 break;
278 HandleReapRequest(fd, iter); 275 HandleReapRequest(fd, iter);
279 return false; 276 return false;
280 case kZygoteCommandGetTerminationStatus: 277 case kZygoteCommandGetTerminationStatus:
281 if (!fds.empty()) 278 if (!fds.empty())
282 break; 279 break;
283 HandleGetTerminationStatus(fd, iter); 280 HandleGetTerminationStatus(fd, iter);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 } 495 }
499 496
500 // In the parent process. 497 // In the parent process.
501 read_pipe.reset(); 498 read_pipe.reset();
502 pid_oracle.reset(); 499 pid_oracle.reset();
503 500
504 // Always receive a real PID from the zygote host, though it might 501 // Always receive a real PID from the zygote host, though it might
505 // be invalid (see below). 502 // be invalid (see below).
506 base::ProcessId real_pid; 503 base::ProcessId real_pid;
507 { 504 {
508 ScopedVector<base::ScopedFD> recv_fds; 505 std::vector<base::ScopedFD> recv_fds;
509 char buf[kZygoteMaxMessageLength]; 506 char buf[kZygoteMaxMessageLength];
510 const ssize_t len = base::UnixDomainSocket::RecvMsg( 507 const ssize_t len = base::UnixDomainSocket::RecvMsg(
511 kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds); 508 kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds);
512 CHECK_GT(len, 0); 509 CHECK_GT(len, 0);
513 CHECK(recv_fds.empty()); 510 CHECK(recv_fds.empty());
514 511
515 base::Pickle pickle(buf, len); 512 base::Pickle pickle(buf, len);
516 base::PickleIterator iter(pickle); 513 base::PickleIterator iter(pickle);
517 514
518 int kind; 515 int kind;
(...skipping 29 matching lines...) Expand all
548 LOG(ERROR) << "Already tracking PID " << real_pid; 545 LOG(ERROR) << "Already tracking PID " << real_pid;
549 NOTREACHED(); 546 NOTREACHED();
550 } 547 }
551 process_info_map_[real_pid].internal_pid = pid; 548 process_info_map_[real_pid].internal_pid = pid;
552 process_info_map_[real_pid].started_from_helper = helper; 549 process_info_map_[real_pid].started_from_helper = helper;
553 550
554 return real_pid; 551 return real_pid;
555 } 552 }
556 553
557 base::ProcessId Zygote::ReadArgsAndFork(base::PickleIterator iter, 554 base::ProcessId Zygote::ReadArgsAndFork(base::PickleIterator iter,
558 ScopedVector<base::ScopedFD> fds, 555 std::vector<base::ScopedFD> fds,
559 std::string* uma_name, 556 std::string* uma_name,
560 int* uma_sample, 557 int* uma_sample,
561 int* uma_boundary_value) { 558 int* uma_boundary_value) {
562 std::vector<std::string> args; 559 std::vector<std::string> args;
563 int argc = 0; 560 int argc = 0;
564 int numfds = 0; 561 int numfds = 0;
565 base::GlobalDescriptors::Mapping mapping; 562 base::GlobalDescriptors::Mapping mapping;
566 std::string process_type; 563 std::string process_type;
567 std::string channel_id; 564 std::string channel_id;
568 const std::string channel_id_prefix = std::string("--") 565 const std::string channel_id_prefix = std::string("--")
(...skipping 14 matching lines...) Expand all
583 } 580 }
584 581
585 if (!iter.ReadInt(&numfds)) 582 if (!iter.ReadInt(&numfds))
586 return -1; 583 return -1;
587 if (numfds != static_cast<int>(fds.size())) 584 if (numfds != static_cast<int>(fds.size()))
588 return -1; 585 return -1;
589 586
590 // First FD is the PID oracle socket. 587 // First FD is the PID oracle socket.
591 if (fds.size() < 1) 588 if (fds.size() < 1)
592 return -1; 589 return -1;
593 base::ScopedFD pid_oracle(std::move(*fds[0])); 590 base::ScopedFD pid_oracle(std::move(fds[0]));
594 591
595 // Remaining FDs are for the global descriptor mapping. 592 // Remaining FDs are for the global descriptor mapping.
596 for (int i = 1; i < numfds; ++i) { 593 for (int i = 1; i < numfds; ++i) {
597 base::GlobalDescriptors::Key key; 594 base::GlobalDescriptors::Key key;
598 if (!iter.ReadUInt32(&key)) 595 if (!iter.ReadUInt32(&key))
599 return -1; 596 return -1;
600 mapping.push_back(base::GlobalDescriptors::Descriptor(key, fds[i]->get())); 597 mapping.push_back(base::GlobalDescriptors::Descriptor(key, fds[i].get()));
601 } 598 }
602 599
603 mapping.push_back(base::GlobalDescriptors::Descriptor( 600 mapping.push_back(base::GlobalDescriptors::Descriptor(
604 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); 601 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
605 602
606 // Returns twice, once per process. 603 // Returns twice, once per process.
607 base::ProcessId child_pid = 604 base::ProcessId child_pid =
608 ForkWithRealPid(process_type, mapping, channel_id, std::move(pid_oracle), 605 ForkWithRealPid(process_type, mapping, channel_id, std::move(pid_oracle),
609 uma_name, uma_sample, uma_boundary_value); 606 uma_name, uma_sample, uma_boundary_value);
610 if (!child_pid) { 607 if (!child_pid) {
611 // This is the child process. 608 // This is the child process.
612 609
613 // Our socket from the browser. 610 // Our socket from the browser.
614 PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd))); 611 PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd)));
615 612
616 // Pass ownership of file descriptors from fds to GlobalDescriptors. 613 // Pass ownership of file descriptors from fds to GlobalDescriptors.
617 for (ScopedVector<base::ScopedFD>::iterator i = fds.begin(); i != fds.end(); 614 for (base::ScopedFD& fd : fds)
618 ++i) 615 ignore_result(fd.release());
619 ignore_result((*i)->release());
620 base::GlobalDescriptors::GetInstance()->Reset(mapping); 616 base::GlobalDescriptors::GetInstance()->Reset(mapping);
621 617
622 // Reset the process-wide command line to our new command line. 618 // Reset the process-wide command line to our new command line.
623 base::CommandLine::Reset(); 619 base::CommandLine::Reset();
624 base::CommandLine::Init(0, NULL); 620 base::CommandLine::Init(0, NULL);
625 base::CommandLine::ForCurrentProcess()->InitFromArgv(args); 621 base::CommandLine::ForCurrentProcess()->InitFromArgv(args);
626 622
627 // Update the process title. The argv was already cached by the call to 623 // Update the process title. The argv was already cached by the call to
628 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here 624 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
629 // (we don't have the original argv at this point). 625 // (we don't have the original argv at this point).
630 SetProcessTitleFromCommandLine(NULL); 626 SetProcessTitleFromCommandLine(NULL);
631 } else if (child_pid < 0) { 627 } else if (child_pid < 0) {
632 LOG(ERROR) << "Zygote could not fork: process_type " << process_type 628 LOG(ERROR) << "Zygote could not fork: process_type " << process_type
633 << " numfds " << numfds << " child_pid " << child_pid; 629 << " numfds " << numfds << " child_pid " << child_pid;
634 } 630 }
635 return child_pid; 631 return child_pid;
636 } 632 }
637 633
638 bool Zygote::HandleForkRequest(int fd, 634 bool Zygote::HandleForkRequest(int fd,
639 base::PickleIterator iter, 635 base::PickleIterator iter,
640 ScopedVector<base::ScopedFD> fds) { 636 std::vector<base::ScopedFD> fds) {
641 std::string uma_name; 637 std::string uma_name;
642 int uma_sample; 638 int uma_sample;
643 int uma_boundary_value; 639 int uma_boundary_value;
644 base::ProcessId child_pid = ReadArgsAndFork( 640 base::ProcessId child_pid = ReadArgsAndFork(iter, std::move(fds), &uma_name,
645 iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value); 641 &uma_sample, &uma_boundary_value);
646 if (child_pid == 0) 642 if (child_pid == 0)
647 return true; 643 return true;
648 // If there's no UMA report for this particular fork, then check if any 644 // If there's no UMA report for this particular fork, then check if any
649 // helpers have an initial UMA report for us to send instead. 645 // helpers have an initial UMA report for us to send instead.
650 while (uma_name.empty() && initial_uma_index_ < helpers_.size()) { 646 while (uma_name.empty() && initial_uma_index_ < helpers_.size()) {
651 helpers_[initial_uma_index_++]->InitialUMA( 647 helpers_[initial_uma_index_++]->InitialUMA(
652 &uma_name, &uma_sample, &uma_boundary_value); 648 &uma_name, &uma_sample, &uma_boundary_value);
653 } 649 }
654 // Must always send reply, as ZygoteHost blocks while waiting for it. 650 // Must always send reply, as ZygoteHost blocks while waiting for it.
655 base::Pickle reply_pickle; 651 base::Pickle reply_pickle;
(...skipping 12 matching lines...) Expand all
668 bool Zygote::HandleGetSandboxStatus(int fd, base::PickleIterator iter) { 664 bool Zygote::HandleGetSandboxStatus(int fd, base::PickleIterator iter) {
669 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != 665 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
670 sizeof(sandbox_flags_)) { 666 sizeof(sandbox_flags_)) {
671 PLOG(ERROR) << "write"; 667 PLOG(ERROR) << "write";
672 } 668 }
673 669
674 return false; 670 return false;
675 } 671 }
676 672
677 } // namespace content 673 } // namespace content
OLDNEW
« no previous file with comments | « content/zygote/zygote_linux.h ('k') | extensions/shell/app/shell_main_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698