Chromium Code Reviews| 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 23 matching lines...) Expand all Loading... | |
| 34 // See http://code.google.com/p/chromium/wiki/LinuxZygote | 34 // See http://code.google.com/p/chromium/wiki/LinuxZygote |
| 35 | 35 |
| 36 namespace content { | 36 namespace content { |
| 37 | 37 |
| 38 namespace { | 38 namespace { |
| 39 | 39 |
| 40 // NOP function. See below where this handler is installed. | 40 // NOP function. See below where this handler is installed. |
| 41 void SIGCHLDHandler(int signal) { | 41 void SIGCHLDHandler(int signal) { |
| 42 } | 42 } |
| 43 | 43 |
| 44 int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) { | |
| 45 for (size_t index = 0; index < fd_mapping.size(); ++index) { | |
| 46 if (fd_mapping[index].first == key) | |
| 47 return fd_mapping[index].second; | |
| 48 } | |
| 49 return -1; | |
| 50 } | |
| 51 | |
| 44 } // namespace | 52 } // namespace |
| 45 | 53 |
| 46 Zygote::Zygote(int sandbox_flags, | 54 Zygote::Zygote(int sandbox_flags, |
| 47 ZygoteForkDelegate* helper) | 55 ZygoteForkDelegate* helper) |
| 48 : sandbox_flags_(sandbox_flags), | 56 : sandbox_flags_(sandbox_flags), |
| 49 helper_(helper), | 57 helper_(helper), |
| 50 initial_uma_sample_(0), | 58 initial_uma_sample_(0), |
| 51 initial_uma_boundary_value_(0) { | 59 initial_uma_boundary_value_(0) { |
| 52 if (helper_) { | 60 if (helper_) { |
| 53 helper_->InitialUMA(&initial_uma_name_, | 61 helper_->InitialUMA(&initial_uma_name_, |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 Pickle write_pickle; | 275 Pickle write_pickle; |
| 268 write_pickle.WriteInt(static_cast<int>(status)); | 276 write_pickle.WriteInt(static_cast<int>(status)); |
| 269 write_pickle.WriteInt(exit_code); | 277 write_pickle.WriteInt(exit_code); |
| 270 ssize_t written = | 278 ssize_t written = |
| 271 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); | 279 HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size())); |
| 272 if (written != static_cast<ssize_t>(write_pickle.size())) | 280 if (written != static_cast<ssize_t>(write_pickle.size())) |
| 273 PLOG(ERROR) << "write"; | 281 PLOG(ERROR) << "write"; |
| 274 } | 282 } |
| 275 | 283 |
| 276 int Zygote::ForkWithRealPid(const std::string& process_type, | 284 int Zygote::ForkWithRealPid(const std::string& process_type, |
| 277 std::vector<int>& fds, | 285 const base::GlobalDescriptors::Mapping& fd_mapping, |
| 278 const std::string& channel_switch, | 286 const std::string& channel_switch, |
| 279 std::string* uma_name, | 287 std::string* uma_name, |
| 280 int* uma_sample, | 288 int* uma_sample, |
| 281 int* uma_boundary_value) { | 289 int* uma_boundary_value) { |
| 282 const bool use_helper = (helper_ && helper_->CanHelp(process_type, | 290 const bool use_helper = (helper_ && helper_->CanHelp(process_type, |
| 283 uma_name, | 291 uma_name, |
| 284 uma_sample, | 292 uma_sample, |
| 285 uma_boundary_value)); | 293 uma_boundary_value)); |
| 286 int dummy_fd; | 294 int dummy_fd; |
| 287 ino_t dummy_inode; | 295 ino_t dummy_inode; |
| 288 int pipe_fds[2] = { -1, -1 }; | 296 int pipe_fds[2] = { -1, -1 }; |
| 289 base::ProcessId pid = 0; | 297 base::ProcessId pid = 0; |
| 290 | 298 |
| 291 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); | 299 dummy_fd = socket(PF_UNIX, SOCK_DGRAM, 0); |
| 292 if (dummy_fd < 0) { | 300 if (dummy_fd < 0) { |
| 293 LOG(ERROR) << "Failed to create dummy FD"; | 301 LOG(ERROR) << "Failed to create dummy FD"; |
| 294 goto error; | 302 goto error; |
| 295 } | 303 } |
| 296 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { | 304 if (!base::FileDescriptorGetInode(&dummy_inode, dummy_fd)) { |
| 297 LOG(ERROR) << "Failed to get inode for dummy FD"; | 305 LOG(ERROR) << "Failed to get inode for dummy FD"; |
| 298 goto error; | 306 goto error; |
| 299 } | 307 } |
| 300 if (pipe(pipe_fds) != 0) { | 308 if (pipe(pipe_fds) != 0) { |
| 301 LOG(ERROR) << "Failed to create pipe"; | 309 LOG(ERROR) << "Failed to create pipe"; |
| 302 goto error; | 310 goto error; |
| 303 } | 311 } |
| 304 | 312 |
| 305 if (use_helper) { | 313 if (use_helper) { |
| 314 std::vector<int> fds; | |
| 315 int ipc_channel_fd = LookUpFd(fd_mapping, kPrimaryIPCChannel); | |
| 316 if (ipc_channel_fd < 0) { | |
| 317 DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping"; | |
| 318 goto error; | |
| 319 } | |
| 320 fds.push_back(ipc_channel_fd); | |
|
jln (very slow on Chromium)
2013/09/30 19:15:39
I don't understand why this works. The size of fds
Mark Seaborn
2013/10/01 22:32:54
I'm not increasing the number of FDs that is sent
jln (very slow on Chromium)
2013/10/01 22:51:46
Ohh yeah of course, sorry I missed that.
Mark Seaborn
2013/10/07 15:23:13
I've made that change. Please take a look.
| |
| 306 fds.push_back(dummy_fd); | 321 fds.push_back(dummy_fd); |
| 307 fds.push_back(pipe_fds[0]); | 322 fds.push_back(pipe_fds[0]); |
| 308 pid = helper_->Fork(fds); | 323 pid = helper_->Fork(fds); |
| 309 } else { | 324 } else { |
| 310 pid = fork(); | 325 pid = fork(); |
| 311 } | 326 } |
| 312 if (pid < 0) { | 327 if (pid < 0) { |
| 313 goto error; | 328 goto error; |
| 314 } else if (pid == 0) { | 329 } else if (pid == 0) { |
| 315 // In the child process. | 330 // In the child process. |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 return -1; | 455 return -1; |
| 441 args.push_back(arg); | 456 args.push_back(arg); |
| 442 if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0) | 457 if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0) |
| 443 channel_id = arg; | 458 channel_id = arg; |
| 444 } | 459 } |
| 445 | 460 |
| 446 if (!pickle.ReadInt(&iter, &numfds)) | 461 if (!pickle.ReadInt(&iter, &numfds)) |
| 447 return -1; | 462 return -1; |
| 448 if (numfds != static_cast<int>(fds.size())) | 463 if (numfds != static_cast<int>(fds.size())) |
| 449 return -1; | 464 return -1; |
| 450 | 465 |
|
jln (very slow on Chromium)
2013/09/30 19:15:39
Do you want to add a comment here explaining a bit
Mark Seaborn
2013/10/01 22:32:54
Something like "// Unmarshal FD mapping"? This pa
jln (very slow on Chromium)
2013/10/01 22:51:46
The whole thing is generally very poorly documente
| |
| 451 for (int i = 0; i < numfds; ++i) { | 466 for (int i = 0; i < numfds; ++i) { |
| 452 base::GlobalDescriptors::Key key; | 467 base::GlobalDescriptors::Key key; |
| 453 if (!pickle.ReadUInt32(&iter, &key)) | 468 if (!pickle.ReadUInt32(&iter, &key)) |
| 454 return -1; | 469 return -1; |
| 455 mapping.push_back(std::make_pair(key, fds[i])); | 470 mapping.push_back(std::make_pair(key, fds[i])); |
| 456 } | 471 } |
| 457 | 472 |
| 458 mapping.push_back(std::make_pair( | 473 mapping.push_back(std::make_pair( |
| 459 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); | 474 static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD())); |
| 460 | 475 |
| 461 // Returns twice, once per process. | 476 // Returns twice, once per process. |
| 462 base::ProcessId child_pid = ForkWithRealPid(process_type, fds, channel_id, | 477 base::ProcessId child_pid = ForkWithRealPid(process_type, mapping, channel_id, |
| 463 uma_name, uma_sample, | 478 uma_name, uma_sample, |
| 464 uma_boundary_value); | 479 uma_boundary_value); |
| 465 if (!child_pid) { | 480 if (!child_pid) { |
| 466 // This is the child process. | 481 // This is the child process. |
| 467 | 482 |
| 468 close(kZygoteSocketPairFd); // Our socket from the browser. | 483 close(kZygoteSocketPairFd); // Our socket from the browser. |
| 469 if (UsingSUIDSandbox()) | 484 if (UsingSUIDSandbox()) |
| 470 close(kZygoteIdFd); // Another socket from the browser. | 485 close(kZygoteIdFd); // Another socket from the browser. |
| 471 base::GlobalDescriptors::GetInstance()->Reset(mapping); | 486 base::GlobalDescriptors::GetInstance()->Reset(mapping); |
| 472 | 487 |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 529 PickleIterator iter) { | 544 PickleIterator iter) { |
| 530 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != | 545 if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) != |
| 531 sizeof(sandbox_flags_)) { | 546 sizeof(sandbox_flags_)) { |
| 532 PLOG(ERROR) << "write"; | 547 PLOG(ERROR) << "write"; |
| 533 } | 548 } |
| 534 | 549 |
| 535 return false; | 550 return false; |
| 536 } | 551 } |
| 537 | 552 |
| 538 } // namespace content | 553 } // namespace content |
| OLD | NEW |