15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/unix_domain_socket_linux.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/socket.h> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <sys/uio.h> 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <unistd.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <vector> 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/files/scoped_file.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/memory/scoped_vector.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t UnixDomainSocket::kMaxFileDescriptors = 16; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Creates a connected pair of UNIX-domain SOCK_SEQPACKET sockets, and passes 245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// ownership of the newly allocated file descriptors to |one| and |two|. 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Returns true on success. 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liustatic bool CreateSocketPair(base::ScopedFD* one, base::ScopedFD* two) { 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu int raw_socks[2]; 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks) == -1) 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu one->reset(raw_socks[0]); 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu two->reset(raw_socks[1]); 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return true; 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// static 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool UnixDomainSocket::EnableReceiveProcessId(int fd) { 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const int enable = 1; 385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable)) == 0; 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool UnixDomainSocket::SendMsg(int fd, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* buf, 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<int>& fds) { 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct msghdr msg = {}; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct iovec iov = { const_cast<void*>(buf), length }; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_iov = &iov; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_iovlen = 1; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* control_buffer = NULL; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fds.size()) { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned control_len = CMSG_SPACE(sizeof(int) * fds.size()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) control_buffer = new char[control_len]; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct cmsghdr* cmsg; 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_control = control_buffer; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_controllen = control_len; 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmsg = CMSG_FIRSTHDR(&msg); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmsg->cmsg_level = SOL_SOCKET; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmsg->cmsg_type = SCM_RIGHTS; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmsg->cmsg_len = CMSG_LEN(sizeof(int) * fds.size()); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(CMSG_DATA(cmsg), &fds[0], sizeof(int) * fds.size()); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_controllen = cmsg->cmsg_len; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Avoid a SIGPIPE if the other end breaks the connection. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Due to a bug in the Linux kernel (net/unix/af_unix.c) MSG_NOSIGNAL isn't 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // regarded for SOCK_SEQPACKET in the AF_UNIX domain, but it is mandated by 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // POSIX. 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int flags = MSG_NOSIGNAL; 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ssize_t r = HANDLE_EINTR(sendmsg(fd, &msg, flags)); 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool ret = static_cast<ssize_t>(length) == r; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] control_buffer; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t UnixDomainSocket::RecvMsg(int fd, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* buf, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length, 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ScopedVector<base::ScopedFD>* fds) { 835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return UnixDomainSocket::RecvMsgWithPid(fd, buf, length, fds, NULL); 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// static 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liussize_t UnixDomainSocket::RecvMsgWithPid(int fd, 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu void* buf, 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu size_t length, 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ScopedVector<base::ScopedFD>* fds, 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::ProcessId* pid) { 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return UnixDomainSocket::RecvMsgWithFlags(fd, buf, length, 0, fds, pid); 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ssize_t UnixDomainSocket::RecvMsgWithFlags(int fd, 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void* buf, 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t length, 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int flags, 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ScopedVector<base::ScopedFD>* fds, 1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::ProcessId* out_pid) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fds->clear(); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct msghdr msg = {}; 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct iovec iov = { buf, length }; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_iov = &iov; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_iovlen = 1; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu char control_buffer[CMSG_SPACE(sizeof(int) * kMaxFileDescriptors) + 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu CMSG_SPACE(sizeof(struct ucred))]; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_control = control_buffer; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg.msg_controllen = sizeof(control_buffer); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ssize_t r = HANDLE_EINTR(recvmsg(fd, &msg, flags)); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r == -1) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* wire_fds = NULL; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned wire_fds_len = 0; 1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::ProcessId pid = -1; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msg.msg_controllen > 0) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct cmsghdr* cmsg; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const unsigned payload_len = cmsg->cmsg_len - CMSG_LEN(0); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cmsg->cmsg_level == SOL_SOCKET && 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cmsg->cmsg_type == SCM_RIGHTS) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(payload_len % sizeof(int) == 0); 1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(wire_fds == NULL); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wire_fds = reinterpret_cast<int*>(CMSG_DATA(cmsg)); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wire_fds_len = payload_len / sizeof(int); 1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (cmsg->cmsg_level == SOL_SOCKET && 1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu cmsg->cmsg_type == SCM_CREDENTIALS) { 1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(payload_len == sizeof(struct ucred)); 1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK(pid == -1); 1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu pid = reinterpret_cast<struct ucred*>(CMSG_DATA(cmsg))->pid; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msg.msg_flags & MSG_TRUNC || msg.msg_flags & MSG_CTRUNC) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0; i < wire_fds_len; ++i) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(wire_fds[i]); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) errno = EMSGSIZE; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (wire_fds) { 1505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu for (unsigned i = 0; i < wire_fds_len; ++i) 1515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu fds->push_back(new base::ScopedFD(wire_fds[i])); 1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 1535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (out_pid) { 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // |pid| will legitimately be -1 if we read EOF, so only DCHECK if we 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // actually received a message. Unfortunately, Linux allows sending zero 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // length messages, which are indistinguishable from EOF, so this check 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // has false negatives. 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (r > 0 || msg.msg_controllen > 0) 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_GE(pid, 0); 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *out_pid = pid; 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return r; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t UnixDomainSocket::SendRecvMsg(int fd, 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint8_t* reply, 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned max_reply_len, 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* result_fd, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Pickle& request) { 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return UnixDomainSocket::SendRecvMsgWithFlags(fd, reply, max_reply_len, 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 0, /* recvmsg_flags */ 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) result_fd, request); 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// static 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)ssize_t UnixDomainSocket::SendRecvMsgWithFlags(int fd, 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) uint8_t* reply, 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned max_reply_len, 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int recvmsg_flags, 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int* result_fd, 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Pickle& request) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This socketpair is only used for the IPC and is cleaned up before 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // returning. 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu base::ScopedFD recv_sock, send_sock; 1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!CreateSocketPair(&recv_sock, &send_sock)) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu { 1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::vector<int> send_fds; 1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu send_fds.push_back(send_sock.get()); 1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (!SendMsg(fd, request.data(), request.size(), send_fds)) 1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return -1; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Close the sending end of the socket right away so that if our peer closes 2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // it before sending a response (e.g., from exiting), RecvMsgWithFlags() will 2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // return EOF instead of hanging. 2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu send_sock.reset(); 2035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 2045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ScopedVector<base::ScopedFD> recv_fds; 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // When porting to OSX keep in mind it doesn't support MSG_NOSIGNAL, so the 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // sender might get a SIGPIPE. 2075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const ssize_t reply_len = RecvMsgWithFlags( 2085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recv_sock.get(), reply, max_reply_len, recvmsg_flags, &recv_fds, NULL); 2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu recv_sock.reset(); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reply_len == -1) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If we received more file descriptors than caller expected, then we treat 2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // that as an error. 2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (recv_fds.size() > (result_fd != NULL ? 1 : 0)) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result_fd) 2215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu *result_fd = recv_fds.empty() ? -1 : recv_fds[0]->release(); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reply_len; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 225