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 "ipc/ipc_channel_posix.h" | 5 #include "ipc/ipc_channel_posix.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <sys/socket.h> | 10 #include <sys/socket.h> |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 240 // 3) It's for a client that we implement ourself. This is used | 240 // 3) It's for a client that we implement ourself. This is used |
| 241 // in single-process unittesting. | 241 // in single-process unittesting. |
| 242 // 4) It's the initial IPC channel: | 242 // 4) It's the initial IPC channel: |
| 243 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. | 243 // 4a) Client side: Pull the pipe out of the GlobalDescriptors set. |
| 244 // 4b) Server side: create the pipe. | 244 // 4b) Server side: create the pipe. |
| 245 | 245 |
| 246 base::ScopedFD local_pipe; | 246 base::ScopedFD local_pipe; |
| 247 if (channel_handle.socket.fd != -1) { | 247 if (channel_handle.socket.fd != -1) { |
| 248 // Case 1 from comment above. | 248 // Case 1 from comment above. |
| 249 local_pipe.reset(channel_handle.socket.fd); | 249 local_pipe.reset(channel_handle.socket.fd); |
| 250 #if defined(IPC_USES_READWRITE) | |
| 251 // Test the socket passed into us to make sure it is nonblocking. | |
| 252 // We don't want to call read/write on a blocking socket. | |
| 253 int value = fcntl(local_pipe.get(), F_GETFL); | |
| 254 if (value == -1) { | |
| 255 PLOG(ERROR) << "fcntl(F_GETFL) " << pipe_name_; | |
| 256 return false; | |
| 257 } | |
| 258 if (!(value & O_NONBLOCK)) { | |
| 259 LOG(ERROR) << "Socket " << pipe_name_ << " must be O_NONBLOCK"; | |
| 260 return false; | |
| 261 } | |
| 262 #endif // IPC_USES_READWRITE | |
| 263 } else if (mode_ & MODE_NAMED_FLAG) { | 250 } else if (mode_ & MODE_NAMED_FLAG) { |
| 264 #if defined(OS_NACL_NONSFI) | 251 #if defined(OS_NACL_NONSFI) |
| 265 LOG(FATAL) | 252 LOG(FATAL) |
| 266 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode."; | 253 << "IPC channels in nacl_helper_nonsfi should not be in NAMED mode."; |
| 267 #else | 254 #else |
| 268 // Case 2 from comment above. | 255 // Case 2 from comment above. |
| 269 int local_pipe_fd = -1; | 256 int local_pipe_fd = -1; |
| 270 | 257 |
| 271 if (mode_ & MODE_SERVER_FLAG) { | 258 if (mode_ & MODE_SERVER_FLAG) { |
| 272 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_), | 259 if (!CreateServerUnixDomainSocket(base::FilePath(pipe_name_), |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 325 if (!SocketPair(&local_pipe_fd, &client_pipe_fd)) | 312 if (!SocketPair(&local_pipe_fd, &client_pipe_fd)) |
| 326 return false; | 313 return false; |
| 327 local_pipe.reset(local_pipe_fd); | 314 local_pipe.reset(local_pipe_fd); |
| 328 client_pipe_.reset(client_pipe_fd); | 315 client_pipe_.reset(client_pipe_fd); |
| 329 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd); | 316 PipeMap::GetInstance()->Insert(pipe_name_, client_pipe_fd); |
| 330 } else { | 317 } else { |
| 331 LOG(ERROR) << "Bad mode: " << mode_; | 318 LOG(ERROR) << "Bad mode: " << mode_; |
| 332 return false; | 319 return false; |
| 333 } | 320 } |
| 334 } | 321 } |
| 335 | 322 |
|
hidehiko
2015/05/18 04:54:05
nit: unnecessary empty line?
mdempsky
2015/05/18 17:58:37
Done.
| |
| 336 #if defined(IPC_USES_READWRITE) | |
| 337 // Create a dedicated socketpair() for exchanging file descriptors. | |
| 338 // See comments for IPC_USES_READWRITE for details. | |
| 339 if (mode_ & MODE_CLIENT_FLAG) { | |
| 340 int fd_pipe_fd = 1, remote_fd_pipe_fd = -1; | |
| 341 if (!SocketPair(&fd_pipe_fd, &remote_fd_pipe_fd)) { | |
| 342 return false; | |
| 343 } | |
| 344 | |
| 345 fd_pipe_.reset(fd_pipe_fd); | |
| 346 remote_fd_pipe_.reset(remote_fd_pipe_fd); | |
| 347 } | |
| 348 #endif // IPC_USES_READWRITE | |
| 349 | 323 |
| 350 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { | 324 if ((mode_ & MODE_SERVER_FLAG) && (mode_ & MODE_NAMED_FLAG)) { |
| 351 #if defined(OS_NACL_NONSFI) | 325 #if defined(OS_NACL_NONSFI) |
| 352 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " | 326 LOG(FATAL) << "IPC channels in nacl_helper_nonsfi " |
| 353 << "should not be in NAMED or SERVER mode."; | 327 << "should not be in NAMED or SERVER mode."; |
| 354 #else | 328 #else |
| 355 server_listen_pipe_.reset(local_pipe.release()); | 329 server_listen_pipe_.reset(local_pipe.release()); |
| 356 #endif | 330 #endif |
| 357 } else { | 331 } else { |
| 358 pipe_.reset(local_pipe.release()); | 332 pipe_.reset(local_pipe.release()); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 cmsg->cmsg_level = SOL_SOCKET; | 433 cmsg->cmsg_level = SOL_SOCKET; |
| 460 cmsg->cmsg_type = SCM_RIGHTS; | 434 cmsg->cmsg_type = SCM_RIGHTS; |
| 461 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); | 435 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds); |
| 462 msg->attachment_set()->PeekDescriptors( | 436 msg->attachment_set()->PeekDescriptors( |
| 463 reinterpret_cast<int*>(CMSG_DATA(cmsg))); | 437 reinterpret_cast<int*>(CMSG_DATA(cmsg))); |
| 464 msgh.msg_controllen = cmsg->cmsg_len; | 438 msgh.msg_controllen = cmsg->cmsg_len; |
| 465 | 439 |
| 466 // DCHECK_LE above already checks that | 440 // DCHECK_LE above already checks that |
| 467 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. | 441 // num_fds < kMaxDescriptorsPerMessage so no danger of overflow. |
| 468 msg->header()->num_fds = static_cast<uint16>(num_fds); | 442 msg->header()->num_fds = static_cast<uint16>(num_fds); |
| 469 | 443 |
|
hidehiko
2015/05/18 04:54:05
nit: unnecessary empty line?
mdempsky
2015/05/18 17:58:36
Done.
| |
| 470 #if defined(IPC_USES_READWRITE) | |
| 471 if (!IsHelloMessage(*msg)) { | |
| 472 // Only the Hello message sends the file descriptor with the message. | |
| 473 // Subsequently, we can send file descriptors on the dedicated | |
| 474 // fd_pipe_ which makes Seccomp sandbox operation more efficient. | |
| 475 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; | |
| 476 msgh.msg_iov = &fd_pipe_iov; | |
| 477 fd_written = fd_pipe_.get(); | |
| 478 bytes_written = | |
| 479 HANDLE_EINTR(sendmsg(fd_pipe_.get(), &msgh, MSG_DONTWAIT)); | |
| 480 msgh.msg_iov = &iov; | |
| 481 msgh.msg_controllen = 0; | |
| 482 if (bytes_written > 0) { | |
| 483 CloseFileDescriptors(msg); | |
| 484 } | |
| 485 } | |
| 486 #endif // IPC_USES_READWRITE | |
| 487 } | 444 } |
| 488 | 445 |
| 489 if (bytes_written == 1) { | 446 if (bytes_written == 1) { |
| 490 fd_written = pipe_.get(); | 447 fd_written = pipe_.get(); |
| 491 #if defined(IPC_USES_READWRITE) | |
| 492 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) { | |
| 493 DCHECK_EQ(msg->attachment_set()->size(), 1U); | |
| 494 } | |
| 495 if (!msgh.msg_controllen) { | |
| 496 bytes_written = | |
| 497 HANDLE_EINTR(write(pipe_.get(), out_bytes, amt_to_write)); | |
| 498 } else | |
| 499 #endif // IPC_USES_READWRITE | |
| 500 { | 448 { |
|
hidehiko
2015/05/18 04:54:05
nit: you do not need this brace pair.
mdempsky
2015/05/18 17:58:37
Done.
| |
| 501 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); | 449 bytes_written = HANDLE_EINTR(sendmsg(pipe_.get(), &msgh, MSG_DONTWAIT)); |
| 502 } | 450 } |
| 503 } | 451 } |
| 504 if (bytes_written > 0) | 452 if (bytes_written > 0) |
| 505 CloseFileDescriptors(msg); | 453 CloseFileDescriptors(msg); |
| 506 | 454 |
| 507 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { | 455 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { |
| 508 // We can't close the pipe here, because calling OnChannelError | 456 // We can't close the pipe here, because calling OnChannelError |
| 509 // may destroy this object, and that would be bad if we are | 457 // may destroy this object, and that would be bad if we are |
| 510 // called from Send(). Instead, we return false and hope the | 458 // called from Send(). Instead, we return false and hope the |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 609 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); | 557 DCHECK(!(mode_ & MODE_SERVER) || HasAcceptedConnection()); |
| 610 return IPC::GetPeerEuid(pipe_.get(), peer_euid); | 558 return IPC::GetPeerEuid(pipe_.get(), peer_euid); |
| 611 } | 559 } |
| 612 #endif | 560 #endif |
| 613 | 561 |
| 614 void ChannelPosix::ResetToAcceptingConnectionState() { | 562 void ChannelPosix::ResetToAcceptingConnectionState() { |
| 615 // Unregister libevent for the unix domain socket and close it. | 563 // Unregister libevent for the unix domain socket and close it. |
| 616 read_watcher_.StopWatchingFileDescriptor(); | 564 read_watcher_.StopWatchingFileDescriptor(); |
| 617 write_watcher_.StopWatchingFileDescriptor(); | 565 write_watcher_.StopWatchingFileDescriptor(); |
| 618 ResetSafely(&pipe_); | 566 ResetSafely(&pipe_); |
| 619 #if defined(IPC_USES_READWRITE) | |
| 620 fd_pipe_.reset(); | |
| 621 remote_fd_pipe_.reset(); | |
| 622 #endif // IPC_USES_READWRITE | |
| 623 | 567 |
| 624 while (!output_queue_.empty()) { | 568 while (!output_queue_.empty()) { |
| 625 Message* m = output_queue_.front(); | 569 Message* m = output_queue_.front(); |
| 626 output_queue_.pop(); | 570 output_queue_.pop(); |
| 627 delete m; | 571 delete m; |
| 628 } | 572 } |
| 629 | 573 |
| 630 // Close any outstanding, received file descriptors. | 574 // Close any outstanding, received file descriptors. |
| 631 ClearInputFDs(); | 575 ClearInputFDs(); |
| 632 | 576 |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 791 } | 735 } |
| 792 | 736 |
| 793 void ChannelPosix::QueueHelloMessage() { | 737 void ChannelPosix::QueueHelloMessage() { |
| 794 // Create the Hello message | 738 // Create the Hello message |
| 795 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, | 739 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE, |
| 796 HELLO_MESSAGE_TYPE, | 740 HELLO_MESSAGE_TYPE, |
| 797 IPC::Message::PRIORITY_NORMAL)); | 741 IPC::Message::PRIORITY_NORMAL)); |
| 798 if (!msg->WriteInt(GetHelloMessageProcId())) { | 742 if (!msg->WriteInt(GetHelloMessageProcId())) { |
| 799 NOTREACHED() << "Unable to pickle hello message proc id"; | 743 NOTREACHED() << "Unable to pickle hello message proc id"; |
| 800 } | 744 } |
| 801 #if defined(IPC_USES_READWRITE) | |
| 802 scoped_ptr<Message> hello; | |
| 803 if (remote_fd_pipe_.is_valid()) { | |
| 804 if (!msg->WriteAttachment( | |
| 805 new internal::PlatformFileAttachment(remote_fd_pipe_.get()))) { | |
| 806 NOTREACHED() << "Unable to pickle hello message file descriptors"; | |
| 807 } | |
| 808 DCHECK_EQ(msg->attachment_set()->size(), 1U); | |
| 809 } | |
| 810 #endif // IPC_USES_READWRITE | |
| 811 output_queue_.push(msg.release()); | 745 output_queue_.push(msg.release()); |
| 812 } | 746 } |
| 813 | 747 |
| 814 ChannelPosix::ReadState ChannelPosix::ReadData( | 748 ChannelPosix::ReadState ChannelPosix::ReadData( |
| 815 char* buffer, | 749 char* buffer, |
| 816 int buffer_len, | 750 int buffer_len, |
| 817 int* bytes_read) { | 751 int* bytes_read) { |
| 818 if (!pipe_.is_valid()) | 752 if (!pipe_.is_valid()) |
| 819 return READ_FAILED; | 753 return READ_FAILED; |
| 820 | 754 |
| 821 struct msghdr msg = {0}; | 755 struct msghdr msg = {0}; |
| 822 | 756 |
| 823 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; | 757 struct iovec iov = {buffer, static_cast<size_t>(buffer_len)}; |
| 824 msg.msg_iov = &iov; | 758 msg.msg_iov = &iov; |
| 825 msg.msg_iovlen = 1; | 759 msg.msg_iovlen = 1; |
| 826 | 760 |
| 827 msg.msg_control = input_cmsg_buf_; | 761 msg.msg_control = input_cmsg_buf_; |
| 828 | 762 |
| 829 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data | 763 // recvmsg() returns 0 if the connection has closed or EAGAIN if no data |
| 830 // is waiting on the pipe. | 764 // is waiting on the pipe. |
| 831 #if defined(IPC_USES_READWRITE) | |
| 832 if (fd_pipe_.is_valid()) { | |
| 833 *bytes_read = HANDLE_EINTR(read(pipe_.get(), buffer, buffer_len)); | |
| 834 msg.msg_controllen = 0; | |
| 835 } else | |
| 836 #endif // IPC_USES_READWRITE | |
| 837 { | 765 { |
|
hidehiko
2015/05/18 04:54:05
nit, you do not need this brace pair.
mdempsky
2015/05/18 17:58:36
Done.
| |
| 838 msg.msg_controllen = sizeof(input_cmsg_buf_); | 766 msg.msg_controllen = sizeof(input_cmsg_buf_); |
| 839 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); | 767 *bytes_read = HANDLE_EINTR(recvmsg(pipe_.get(), &msg, MSG_DONTWAIT)); |
| 840 } | 768 } |
| 841 if (*bytes_read < 0) { | 769 if (*bytes_read < 0) { |
| 842 if (errno == EAGAIN) { | 770 if (errno == EAGAIN) { |
| 843 return READ_PENDING; | 771 return READ_PENDING; |
| 844 #if defined(OS_MACOSX) | 772 #if defined(OS_MACOSX) |
| 845 } else if (errno == EPERM) { | 773 } else if (errno == EPERM) { |
| 846 // On OSX, reading from a pipe with no listener returns EPERM | 774 // On OSX, reading from a pipe with no listener returns EPERM |
| 847 // treat this as a special case to prevent spurious error messages | 775 // treat this as a special case to prevent spurious error messages |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 861 DCHECK(*bytes_read); | 789 DCHECK(*bytes_read); |
| 862 | 790 |
| 863 CloseClientFileDescriptor(); | 791 CloseClientFileDescriptor(); |
| 864 | 792 |
| 865 // Read any file descriptors from the message. | 793 // Read any file descriptors from the message. |
| 866 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | 794 if (!ExtractFileDescriptorsFromMsghdr(&msg)) |
| 867 return READ_FAILED; | 795 return READ_FAILED; |
| 868 return READ_SUCCEEDED; | 796 return READ_SUCCEEDED; |
| 869 } | 797 } |
| 870 | 798 |
| 871 #if defined(IPC_USES_READWRITE) | |
| 872 bool ChannelPosix::ReadFileDescriptorsFromFDPipe() { | |
| 873 char dummy; | |
| 874 struct iovec fd_pipe_iov = { &dummy, 1 }; | |
| 875 | |
| 876 struct msghdr msg = { 0 }; | |
| 877 msg.msg_iov = &fd_pipe_iov; | |
| 878 msg.msg_iovlen = 1; | |
| 879 msg.msg_control = input_cmsg_buf_; | |
| 880 msg.msg_controllen = sizeof(input_cmsg_buf_); | |
| 881 ssize_t bytes_received = | |
| 882 HANDLE_EINTR(recvmsg(fd_pipe_.get(), &msg, MSG_DONTWAIT)); | |
| 883 | |
| 884 if (bytes_received != 1) | |
| 885 return true; // No message waiting. | |
| 886 | |
| 887 if (!ExtractFileDescriptorsFromMsghdr(&msg)) | |
| 888 return false; | |
| 889 return true; | |
| 890 } | |
| 891 #endif | |
| 892 | 799 |
| 893 // On Posix, we need to fix up the file descriptors before the input message | 800 // On Posix, we need to fix up the file descriptors before the input message |
| 894 // is dispatched. | 801 // is dispatched. |
| 895 // | 802 // |
| 896 // This will read from the input_fds_ (READWRITE mode only) and read more | 803 // This will read from the input_fds_ (READWRITE mode only) and read more |
| 897 // handles from the FD pipe if necessary. | 804 // handles from the FD pipe if necessary. |
| 898 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { | 805 bool ChannelPosix::WillDispatchInputMessage(Message* msg) { |
| 899 uint16 header_fds = msg->header()->num_fds; | 806 uint16 header_fds = msg->header()->num_fds; |
| 900 if (!header_fds) | 807 if (!header_fds) |
| 901 return true; // Nothing to do. | 808 return true; // Nothing to do. |
| 902 | 809 |
| 903 // The message has file descriptors. | 810 // The message has file descriptors. |
| 904 const char* error = NULL; | 811 const char* error = NULL; |
| 905 if (header_fds > input_fds_.size()) { | 812 if (header_fds > input_fds_.size()) { |
| 906 // The message has been completely received, but we didn't get | 813 // The message has been completely received, but we didn't get |
| 907 // enough file descriptors. | 814 // enough file descriptors. |
| 908 #if defined(IPC_USES_READWRITE) | |
| 909 if (!ReadFileDescriptorsFromFDPipe()) | |
| 910 return false; | |
| 911 if (header_fds > input_fds_.size()) | |
| 912 #endif // IPC_USES_READWRITE | |
| 913 error = "Message needs unreceived descriptors"; | 815 error = "Message needs unreceived descriptors"; |
|
hidehiko
2015/05/18 04:54:05
nit: indent?
mdempsky
2015/05/18 17:58:37
Done.
| |
| 914 } | 816 } |
| 915 | 817 |
| 916 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) | 818 if (header_fds > MessageAttachmentSet::kMaxDescriptorsPerMessage) |
| 917 error = "Message requires an excessive number of descriptors"; | 819 error = "Message requires an excessive number of descriptors"; |
| 918 | 820 |
| 919 if (error) { | 821 if (error) { |
| 920 LOG(WARNING) << error | 822 LOG(WARNING) << error |
| 921 << " channel:" << this | 823 << " channel:" << this |
| 922 << " message-type:" << msg->type() | 824 << " message-type:" << msg->type() |
| 923 << " header()->num_fds:" << header_fds; | 825 << " header()->num_fds:" << header_fds; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1010 switch (msg.type()) { | 912 switch (msg.type()) { |
| 1011 default: | 913 default: |
| 1012 NOTREACHED(); | 914 NOTREACHED(); |
| 1013 break; | 915 break; |
| 1014 | 916 |
| 1015 case Channel::HELLO_MESSAGE_TYPE: | 917 case Channel::HELLO_MESSAGE_TYPE: |
| 1016 int pid; | 918 int pid; |
| 1017 if (!iter.ReadInt(&pid)) | 919 if (!iter.ReadInt(&pid)) |
| 1018 NOTREACHED(); | 920 NOTREACHED(); |
| 1019 | 921 |
| 1020 #if defined(IPC_USES_READWRITE) | |
| 1021 if (mode_ & MODE_SERVER_FLAG) { | |
| 1022 // With IPC_USES_READWRITE, the Hello message from the client to the | |
| 1023 // server also contains the fd_pipe_, which will be used for all | |
| 1024 // subsequent file descriptor passing. | |
| 1025 DCHECK_EQ(msg.attachment_set()->size(), 1U); | |
| 1026 scoped_refptr<MessageAttachment> attachment; | |
| 1027 if (!msg.ReadAttachment(&iter, &attachment)) { | |
| 1028 NOTREACHED(); | |
| 1029 } | |
| 1030 fd_pipe_.reset(attachment->TakePlatformFile()); | |
| 1031 } | |
| 1032 #endif // IPC_USES_READWRITE | |
| 1033 peer_pid_ = pid; | 922 peer_pid_ = pid; |
| 1034 listener()->OnChannelConnected(pid); | 923 listener()->OnChannelConnected(pid); |
| 1035 break; | 924 break; |
| 1036 | 925 |
| 1037 #if defined(OS_MACOSX) | 926 #if defined(OS_MACOSX) |
| 1038 case Channel::CLOSE_FD_MESSAGE_TYPE: | 927 case Channel::CLOSE_FD_MESSAGE_TYPE: |
| 1039 int fd, hops; | 928 int fd, hops; |
| 1040 if (!iter.ReadInt(&hops)) | 929 if (!iter.ReadInt(&hops)) |
| 1041 NOTREACHED(); | 930 NOTREACHED(); |
| 1042 if (!iter.ReadInt(&fd)) | 931 if (!iter.ReadInt(&fd)) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1136 } | 1025 } |
| 1137 | 1026 |
| 1138 #if defined(OS_LINUX) | 1027 #if defined(OS_LINUX) |
| 1139 // static | 1028 // static |
| 1140 void Channel::SetGlobalPid(int pid) { | 1029 void Channel::SetGlobalPid(int pid) { |
| 1141 ChannelPosix::SetGlobalPid(pid); | 1030 ChannelPosix::SetGlobalPid(pid); |
| 1142 } | 1031 } |
| 1143 #endif // OS_LINUX | 1032 #endif // OS_LINUX |
| 1144 | 1033 |
| 1145 } // namespace IPC | 1034 } // namespace IPC |
| OLD | NEW |