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

Side by Side Diff: util/mach/child_port_handshake.cc

Issue 777573002: ChildPortHandshake: 10.6 fix (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 6 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "util/mach/child_port_handshake.h" 15 #include "util/mach/child_port_handshake.h"
16 16
17 #include <errno.h> 17 #include <errno.h>
18 #include <fcntl.h>
19 #include <pthread.h> 18 #include <pthread.h>
20 #include <servers/bootstrap.h> 19 #include <servers/bootstrap.h>
21 #include <sys/event.h> 20 #include <sys/event.h>
21 #include <sys/socket.h>
22 #include <sys/time.h> 22 #include <sys/time.h>
23 #include <sys/types.h> 23 #include <sys/types.h>
24 #include <unistd.h> 24 #include <unistd.h>
25 25
26 #include <algorithm> 26 #include <algorithm>
27 27
28 #include "base/logging.h" 28 #include "base/logging.h"
29 #include "base/mac/mach_logging.h" 29 #include "base/mac/mach_logging.h"
30 #include "base/mac/scoped_mach_port.h" 30 #include "base/mac/scoped_mach_port.h"
31 #include "base/posix/eintr_wrapper.h" 31 #include "base/posix/eintr_wrapper.h"
32 #include "base/rand_util.h" 32 #include "base/rand_util.h"
33 #include "base/strings/stringprintf.h" 33 #include "base/strings/stringprintf.h"
34 #include "util/file/fd_io.h" 34 #include "util/file/fd_io.h"
35 #include "util/mach/child_port.h" 35 #include "util/mach/child_port.h"
36 #include "util/mach/mach_extensions.h" 36 #include "util/mach/mach_extensions.h"
37 #include "util/mach/mach_message_server.h" 37 #include "util/mach/mach_message_server.h"
38 38
39 namespace crashpad { 39 namespace crashpad {
40 40
41 ChildPortHandshake::ChildPortHandshake() 41 ChildPortHandshake::ChildPortHandshake()
42 : token_(0), 42 : token_(0),
43 pipe_read_(), 43 pipe_read_(),
44 pipe_write_(), 44 pipe_write_(),
45 child_port_(MACH_PORT_NULL), 45 child_port_(MACH_PORT_NULL),
46 checked_in_(false) { 46 checked_in_(false) {
47 // Use socketpair() instead of pipe(). There is no way to suppress SIGPIPE on
48 // pipes in Mac OS X 10.6, because the F_SETNOSIGPIPE fcntl() command was not
49 // introduced until 10.7.
47 int pipe_fds[2]; 50 int pipe_fds[2];
48 int rv = pipe(pipe_fds); 51 PCHECK(socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fds) == 0)
49 PCHECK(rv == 0) << "pipe"; 52 << "socketpair";
50 53
51 pipe_read_.reset(pipe_fds[0]); 54 pipe_read_.reset(pipe_fds[0]);
52 pipe_write_.reset(pipe_fds[1]); 55 pipe_write_.reset(pipe_fds[1]);
53 56
57 // Simulate pipe() semantics by shutting down the “wrong” sides of the socket.
58 PCHECK(shutdown(pipe_write_.get(), SHUT_RD) == 0) << "shutdown";
59 PCHECK(shutdown(pipe_read_.get(), SHUT_WR) == 0) << "shutdown";
60
54 // SIGPIPE is undesirable when writing to this pipe. Allow broken-pipe writes 61 // SIGPIPE is undesirable when writing to this pipe. Allow broken-pipe writes
55 // to fail with EPIPE instead. 62 // to fail with EPIPE instead.
56 PCHECK(fcntl(pipe_write_.get(), F_SETNOSIGPIPE, 1) == 0) << "fcntl"; 63 const int value = 1;
64 PCHECK(setsockopt(
65 pipe_write_.get(), SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value)) == 0)
66 << "setsockopt";
57 } 67 }
58 68
59 ChildPortHandshake::~ChildPortHandshake() { 69 ChildPortHandshake::~ChildPortHandshake() {
60 } 70 }
61 71
62 int ChildPortHandshake::ReadPipeFD() const { 72 int ChildPortHandshake::ReadPipeFD() const {
63 DCHECK_NE(pipe_read_.get(), -1); 73 DCHECK_NE(pipe_read_.get(), -1);
64 return pipe_read_.get(); 74 return pipe_read_.get();
65 } 75 }
66 76
67 mach_port_t ChildPortHandshake::RunServer() { 77 mach_port_t ChildPortHandshake::RunServer() {
68 DCHECK_NE(pipe_read_.get(), -1); 78 DCHECK_NE(pipe_read_.get(), -1);
69 pipe_read_.reset(); 79 pipe_read_.reset();
70 80
71 // Transfer ownership of the write pipe into this method’s scope. 81 // Transfer ownership of the write pipe into this method’s scope.
72 base::ScopedFD pipe_write_owner(pipe_write_.release()); 82 base::ScopedFD pipe_write_owner(pipe_write_.release());
73 83
74 // Initialize the token and share it with the client via the pipe. 84 // Initialize the token and share it with the client via the pipe.
75 token_ = base::RandUint64(); 85 token_ = base::RandUint64();
76 int pipe_write = pipe_write_owner.get(); 86 int pipe_write = pipe_write_owner.get();
77 if (!LoggingWriteFD(pipe_write, &token_, sizeof(token_))) { 87 if (!LoggingWriteFD(pipe_write, &token_, sizeof(token_))) {
88 LOG(WARNING) << "no client check-in";
78 return MACH_PORT_NULL; 89 return MACH_PORT_NULL;
79 } 90 }
80 91
81 // Create a unique name for the bootstrap service mapping. Make it unguessable 92 // Create a unique name for the bootstrap service mapping. Make it unguessable
82 // to prevent outsiders from grabbing the name first, which would cause 93 // to prevent outsiders from grabbing the name first, which would cause
83 // bootstrap_check_in() to fail. 94 // bootstrap_check_in() to fail.
84 uint64_t thread_id; 95 uint64_t thread_id;
85 errno = pthread_threadid_np(pthread_self(), &thread_id); 96 errno = pthread_threadid_np(pthread_self(), &thread_id);
86 PCHECK(errno == 0) << "pthread_threadid_np"; 97 PCHECK(errno == 0) << "pthread_threadid_np";
87 std::string service_name = base::StringPrintf( 98 std::string service_name = base::StringPrintf(
88 "com.googlecode.crashpad.child_port_handshake.%d.%llu.%016llx", 99 "com.googlecode.crashpad.child_port_handshake.%d.%llu.%016llx",
89 getpid(), 100 getpid(),
90 thread_id, 101 thread_id,
91 base::RandUint64()); 102 base::RandUint64());
92 DCHECK_LT(service_name.size(), implicit_cast<size_t>(BOOTSTRAP_MAX_NAME_LEN)); 103 DCHECK_LT(service_name.size(), implicit_cast<size_t>(BOOTSTRAP_MAX_NAME_LEN));
93 104
94 // Check the new service in with the bootstrap server, obtaining a receive 105 // Check the new service in with the bootstrap server, obtaining a receive
95 // right for it. 106 // right for it.
96 mach_port_t server_port; 107 mach_port_t server_port;
97 kern_return_t kr = 108 kern_return_t kr =
98 bootstrap_check_in(bootstrap_port, service_name.c_str(), &server_port); 109 bootstrap_check_in(bootstrap_port, service_name.c_str(), &server_port);
99 BOOTSTRAP_CHECK(kr == BOOTSTRAP_SUCCESS, kr) << "bootstrap_check_in"; 110 BOOTSTRAP_CHECK(kr == BOOTSTRAP_SUCCESS, kr) << "bootstrap_check_in";
100 base::mac::ScopedMachReceiveRight server_port_owner(server_port); 111 base::mac::ScopedMachReceiveRight server_port_owner(server_port);
101 112
102 // Share the service name with the client via the pipe. 113 // Share the service name with the client via the pipe.
103 uint32_t service_name_length = service_name.size(); 114 uint32_t service_name_length = service_name.size();
104 if (!LoggingWriteFD( 115 if (!LoggingWriteFD(
105 pipe_write, &service_name_length, sizeof(service_name_length))) { 116 pipe_write, &service_name_length, sizeof(service_name_length))) {
117 LOG(WARNING) << "no client check-in";
106 return MACH_PORT_NULL; 118 return MACH_PORT_NULL;
107 } 119 }
108 120
109 if (!LoggingWriteFD(pipe_write, service_name.c_str(), service_name_length)) { 121 if (!LoggingWriteFD(pipe_write, service_name.c_str(), service_name_length)) {
122 LOG(WARNING) << "no client check-in";
110 return MACH_PORT_NULL; 123 return MACH_PORT_NULL;
111 } 124 }
112 125
113 // A kqueue cannot monitor a raw Mach receive right with EVFILT_MACHPORT. It 126 // A kqueue cannot monitor a raw Mach receive right with EVFILT_MACHPORT. It
114 // requires a port set. Create a new port set and add the receive right to it. 127 // requires a port set. Create a new port set and add the receive right to it.
115 mach_port_t server_port_set; 128 mach_port_t server_port_set;
116 kr = mach_port_allocate( 129 kr = mach_port_allocate(
117 mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &server_port_set); 130 mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &server_port_set);
118 MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_allocate"; 131 MACH_CHECK(kr == KERN_SUCCESS, kr) << "mach_port_allocate";
119 base::mac::ScopedMachPortSet server_port_set_owner(server_port_set); 132 base::mac::ScopedMachPortSet server_port_set_owner(server_port_set);
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 bootstrap_look_up(bootstrap_port, service_name.c_str(), &server_port); 340 bootstrap_look_up(bootstrap_port, service_name.c_str(), &server_port);
328 BOOTSTRAP_CHECK(kr == BOOTSTRAP_SUCCESS, kr) << "bootstrap_look_up"; 341 BOOTSTRAP_CHECK(kr == BOOTSTRAP_SUCCESS, kr) << "bootstrap_look_up";
329 base::mac::ScopedMachSendRight server_port_owner(server_port); 342 base::mac::ScopedMachSendRight server_port_owner(server_port);
330 343
331 // Check in with the server. 344 // Check in with the server.
332 kr = child_port_check_in(server_port, token, port, right_type); 345 kr = child_port_check_in(server_port, token, port, right_type);
333 MACH_CHECK(kr == KERN_SUCCESS, kr) << "child_port_check_in"; 346 MACH_CHECK(kr == KERN_SUCCESS, kr) << "child_port_check_in";
334 } 347 }
335 348
336 } // namespace crashpad 349 } // namespace crashpad
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698