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

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

Issue 258543006: Change UnixDomainSocket::RecvMsg to return ScopedVector<base::ScopedFD> (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Remove fds->{empty,reserve}() per brettw@ feedback Created 6 years, 7 months 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 | Annotate | Revision Log
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 <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>
11 #include <sys/wait.h> 11 #include <sys/wait.h>
12 12
13 #include "base/command_line.h" 13 #include "base/command_line.h"
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "base/file_util.h" 15 #include "base/file_util.h"
16 #include "base/linux_util.h" 16 #include "base/linux_util.h"
17 #include "base/logging.h" 17 #include "base/logging.h"
18 #include "base/macros.h"
18 #include "base/pickle.h" 19 #include "base/pickle.h"
19 #include "base/posix/eintr_wrapper.h" 20 #include "base/posix/eintr_wrapper.h"
20 #include "base/posix/global_descriptors.h" 21 #include "base/posix/global_descriptors.h"
21 #include "base/posix/unix_domain_socket_linux.h" 22 #include "base/posix/unix_domain_socket_linux.h"
22 #include "base/process/kill.h" 23 #include "base/process/kill.h"
23 #include "content/common/child_process_sandbox_support_impl_linux.h" 24 #include "content/common/child_process_sandbox_support_impl_linux.h"
24 #include "content/common/sandbox_linux/sandbox_linux.h" 25 #include "content/common/sandbox_linux/sandbox_linux.h"
25 #include "content/common/set_process_title.h" 26 #include "content/common/set_process_title.h"
26 #include "content/common/zygote_commands_linux.h" 27 #include "content/common/zygote_commands_linux.h"
27 #include "content/public/common/content_descriptors.h" 28 #include "content/public/common/content_descriptors.h"
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 } 116 }
116 *process_info = it->second; 117 *process_info = it->second;
117 return true; 118 return true;
118 } 119 }
119 120
120 bool Zygote::UsingSUIDSandbox() const { 121 bool Zygote::UsingSUIDSandbox() const {
121 return sandbox_flags_ & kSandboxLinuxSUID; 122 return sandbox_flags_ & kSandboxLinuxSUID;
122 } 123 }
123 124
124 bool Zygote::HandleRequestFromBrowser(int fd) { 125 bool Zygote::HandleRequestFromBrowser(int fd) {
125 std::vector<int> fds; 126 ScopedVector<base::ScopedFD> fds;
126 char buf[kZygoteMaxMessageLength]; 127 char buf[kZygoteMaxMessageLength];
127 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds); 128 const ssize_t len = UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
128 129
129 if (len == 0 || (len == -1 && errno == ECONNRESET)) { 130 if (len == 0 || (len == -1 && errno == ECONNRESET)) {
130 // EOF from the browser. We should die. 131 // EOF from the browser. We should die.
131 _exit(0); 132 _exit(0);
132 return false; 133 return false;
133 } 134 }
134 135
135 if (len == -1) { 136 if (len == -1) {
136 PLOG(ERROR) << "Error reading message from browser"; 137 PLOG(ERROR) << "Error reading message from browser";
137 return false; 138 return false;
138 } 139 }
139 140
140 Pickle pickle(buf, len); 141 Pickle pickle(buf, len);
141 PickleIterator iter(pickle); 142 PickleIterator iter(pickle);
142 143
143 int kind; 144 int kind;
144 if (pickle.ReadInt(&iter, &kind)) { 145 if (pickle.ReadInt(&iter, &kind)) {
145 switch (kind) { 146 switch (kind) {
146 case kZygoteCommandFork: 147 case kZygoteCommandFork:
147 // This function call can return multiple times, once per fork(). 148 // This function call can return multiple times, once per fork().
148 return HandleForkRequest(fd, pickle, iter, fds); 149 return HandleForkRequest(fd, pickle, iter, fds.Pass());
149 150
150 case kZygoteCommandReap: 151 case kZygoteCommandReap:
151 if (!fds.empty()) 152 if (!fds.empty())
152 break; 153 break;
153 HandleReapRequest(fd, pickle, iter); 154 HandleReapRequest(fd, pickle, iter);
154 return false; 155 return false;
155 case kZygoteCommandGetTerminationStatus: 156 case kZygoteCommandGetTerminationStatus:
156 if (!fds.empty()) 157 if (!fds.empty())
157 break; 158 break;
158 HandleGetTerminationStatus(fd, pickle, iter); 159 HandleGetTerminationStatus(fd, pickle, iter);
159 return false; 160 return false;
160 case kZygoteCommandGetSandboxStatus: 161 case kZygoteCommandGetSandboxStatus:
161 HandleGetSandboxStatus(fd, pickle, iter); 162 HandleGetSandboxStatus(fd, pickle, iter);
162 return false; 163 return false;
163 default: 164 default:
164 NOTREACHED(); 165 NOTREACHED();
165 break; 166 break;
166 } 167 }
167 } 168 }
168 169
169 LOG(WARNING) << "Error parsing message from browser"; 170 LOG(WARNING) << "Error parsing message from browser";
170 for (std::vector<int>::const_iterator
171 i = fds.begin(); i != fds.end(); ++i)
172 close(*i);
173 return false; 171 return false;
174 } 172 }
175 173
176 // TODO(jln): remove callers to this broken API. See crbug.com/274855. 174 // TODO(jln): remove callers to this broken API. See crbug.com/274855.
177 void Zygote::HandleReapRequest(int fd, 175 void Zygote::HandleReapRequest(int fd,
178 const Pickle& pickle, 176 const Pickle& pickle,
179 PickleIterator iter) { 177 PickleIterator iter) {
180 base::ProcessId child; 178 base::ProcessId child;
181 179
182 if (!pickle.ReadInt(&iter, &child)) { 180 if (!pickle.ReadInt(&iter, &child)) {
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 close(dummy_fd); 430 close(dummy_fd);
433 if (pipe_fds[0] >= 0) 431 if (pipe_fds[0] >= 0)
434 close(pipe_fds[0]); 432 close(pipe_fds[0]);
435 if (pipe_fds[1] >= 0) 433 if (pipe_fds[1] >= 0)
436 close(pipe_fds[1]); 434 close(pipe_fds[1]);
437 return -1; 435 return -1;
438 } 436 }
439 437
440 base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle, 438 base::ProcessId Zygote::ReadArgsAndFork(const Pickle& pickle,
441 PickleIterator iter, 439 PickleIterator iter,
442 std::vector<int>& fds, 440 ScopedVector<base::ScopedFD> fds,
443 std::string* uma_name, 441 std::string* uma_name,
444 int* uma_sample, 442 int* uma_sample,
445 int* uma_boundary_value) { 443 int* uma_boundary_value) {
446 std::vector<std::string> args; 444 std::vector<std::string> args;
447 int argc = 0; 445 int argc = 0;
448 int numfds = 0; 446 int numfds = 0;
449 base::GlobalDescriptors::Mapping mapping; 447 base::GlobalDescriptors::Mapping mapping;
450 std::string process_type; 448 std::string process_type;
451 std::string channel_id; 449 std::string channel_id;
452 const std::string channel_id_prefix = std::string("--") 450 const std::string channel_id_prefix = std::string("--")
(...skipping 15 matching lines...) Expand all
468 466
469 if (!pickle.ReadInt(&iter, &numfds)) 467 if (!pickle.ReadInt(&iter, &numfds))
470 return -1; 468 return -1;
471 if (numfds != static_cast<int>(fds.size())) 469 if (numfds != static_cast<int>(fds.size()))
472 return -1; 470 return -1;
473 471
474 for (int i = 0; i < numfds; ++i) { 472 for (int i = 0; i < numfds; ++i) {
475 base::GlobalDescriptors::Key key; 473 base::GlobalDescriptors::Key key;
476 if (!pickle.ReadUInt32(&iter, &key)) 474 if (!pickle.ReadUInt32(&iter, &key))
477 return -1; 475 return -1;
478 mapping.push_back(std::make_pair(key, fds[i])); 476 mapping.push_back(std::make_pair(key, fds[i]->get()));
479 } 477 }
480 478
481 mapping.push_back(std::make_pair( 479 mapping.push_back(std::make_pair(
482 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); 480 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
483 481
484 // Returns twice, once per process. 482 // Returns twice, once per process.
485 base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id, 483 base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id,
486 uma_name, uma_sample, 484 uma_name, uma_sample,
487 uma_boundary_value); 485 uma_boundary_value);
488 if (!child_pid) { 486 if (!child_pid) {
489 // This is the child process. 487 // This is the child process.
490 488
491 close(kZygoteSocketPairFd); // Our socket from the browser. 489 close(kZygoteSocketPairFd); // Our socket from the browser.
jln (very slow on Chromium) 2014/04/28 23:48:55 This is not passed in fds I suppose? Do you mind a
mdempsky 2014/04/29 00:10:33 Correct. There's no ScopedFD that owns this socke
490
491 // Pass ownership of file descriptors from fds to GlobalDescriptors.
492 for (ScopedVector<base::ScopedFD>::iterator i = fds.begin(); i != fds.end();
jln (very slow on Chromium) 2014/04/28 23:48:55 Wouldn't it be cleaner to iterate on "mapping" ins
mdempsky 2014/04/29 00:10:33 Probably, but as discussed, |mapping| just has the
493 ++i)
494 ignore_result((*i)->release());
492 base::GlobalDescriptors::GetInstance()->Reset(mapping); 495 base::GlobalDescriptors::GetInstance()->Reset(mapping);
493 496
494 // Reset the process-wide command line to our new command line. 497 // Reset the process-wide command line to our new command line.
495 CommandLine::Reset(); 498 CommandLine::Reset();
496 CommandLine::Init(0, NULL); 499 CommandLine::Init(0, NULL);
497 CommandLine::ForCurrentProcess()->InitFromArgv(args); 500 CommandLine::ForCurrentProcess()->InitFromArgv(args);
498 501
499 // Update the process title. The argv was already cached by the call to 502 // Update the process title. The argv was already cached by the call to
500 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here 503 // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
501 // (we don't have the original argv at this point). 504 // (we don't have the original argv at this point).
502 SetProcessTitleFromCommandLine(NULL); 505 SetProcessTitleFromCommandLine(NULL);
503 } else if (child_pid < 0) { 506 } else if (child_pid < 0) {
504 LOG(ERROR) << "Zygote could not fork: process_type " << process_type 507 LOG(ERROR) << "Zygote could not fork: process_type " << process_type
505 << " numfds " << numfds << " child_pid " << child_pid; 508 << " numfds " << numfds << " child_pid " << child_pid;
506 } 509 }
507 return child_pid; 510 return child_pid;
508 } 511 }
509 512
510 bool Zygote::HandleForkRequest(int fd, 513 bool Zygote::HandleForkRequest(int fd,
511 const Pickle& pickle, 514 const Pickle& pickle,
512 PickleIterator iter, 515 PickleIterator iter,
513 std::vector<int>& fds) { 516 ScopedVector<base::ScopedFD> fds) {
514 std::string uma_name; 517 std::string uma_name;
515 int uma_sample; 518 int uma_sample;
516 int uma_boundary_value; 519 int uma_boundary_value;
517 base::ProcessId child_pid = ReadArgsAndFork(pickle, iter, fds, 520 base::ProcessId child_pid = ReadArgsAndFork(
518 &uma_name, &uma_sample, 521 pickle, iter, fds.Pass(), &uma_name, &uma_sample, &uma_boundary_value);
519 &uma_boundary_value);
520 if (child_pid == 0) 522 if (child_pid == 0)
521 return true; 523 return true;
522 for (std::vector<int>::const_iterator
523 i = fds.begin(); i != fds.end(); ++i)
524 close(*i);
525 if (uma_name.empty()) { 524 if (uma_name.empty()) {
526 // There is no UMA report from this particular fork. 525 // There is no UMA report from this particular fork.
527 // Use the initial UMA report if any, and clear that record for next time. 526 // Use the initial UMA report if any, and clear that record for next time.
528 // Note the swap method here is the efficient way to do this, since 527 // Note the swap method here is the efficient way to do this, since
529 // we know uma_name is empty. 528 // we know uma_name is empty.
530 uma_name.swap(initial_uma_name_); 529 uma_name.swap(initial_uma_name_);
531 uma_sample = initial_uma_sample_; 530 uma_sample = initial_uma_sample_;
532 uma_boundary_value = initial_uma_boundary_value_; 531 uma_boundary_value = initial_uma_boundary_value_;
533 } 532 }
534 // Must always send reply, as ZygoteHost blocks while waiting for it. 533 // Must always send reply, as ZygoteHost blocks while waiting for it.
(...skipping 15 matching lines...) Expand all
550 PickleIterator iter) { 549 PickleIterator iter) {
551 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != 550 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
552 sizeof(sandbox_flags_)) { 551 sizeof(sandbox_flags_)) {
553 PLOG(ERROR) << "write"; 552 PLOG(ERROR) << "write";
554 } 553 }
555 554
556 return false; 555 return false;
557 } 556 }
558 557
559 } // namespace content 558 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698