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

Side by Side Diff: ipc/ipc_channel_posix.cc

Issue 25325002: workaround for mac kernel bug (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: enabling fix Created 7 years, 2 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 "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 329 matching lines...) Expand 10 before | Expand all | Expand 10 after
340 true, 340 true,
341 base::MessageLoopForIO::WATCH_READ, 341 base::MessageLoopForIO::WATCH_READ,
342 &server_listen_connection_watcher_, 342 &server_listen_connection_watcher_,
343 this); 343 this);
344 } else { 344 } else {
345 did_connect = AcceptConnection(); 345 did_connect = AcceptConnection();
346 } 346 }
347 return did_connect; 347 return did_connect;
348 } 348 }
349 349
350 void Channel::ChannelImpl::CloseFileDescriptors(Message* msg) {
351 #if defined(OS_MACOSX)
352 // There is a bug on OSX which makes it dangerous to close
353 // a file descriptor while it is in transit. So instead we
354 // store the file descriptor in a set and send a message to
355 // the recipient, which is queued AFTER the message that
356 // sent the FD. The recipient will reply to the message,
357 // letting us know that it is now safe to close the file
358 // descriptor. For more information, see:
359 // http://crbug.com/298276
360 std::vector<int> to_close;
361 msg->file_descriptor_set()->GetFDsToCloseAndClear(&to_close);
362 for (size_t i = 0; i < to_close.size(); i++) {
363 fds_to_close_.insert(to_close[i]);
364 QueueCloseFDMessage(to_close[i], 2);
365 }
366 #else
367 msg->file_descriptor_set()->CommitAll();
368 #endif
369 }
370
agl 2013/10/09 21:52:38 this file only has a single newline after function
hubbe 2013/10/09 21:59:40 Done.
371
350 bool Channel::ChannelImpl::ProcessOutgoingMessages() { 372 bool Channel::ChannelImpl::ProcessOutgoingMessages() {
351 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's 373 DCHECK(!waiting_connect_); // Why are we trying to send messages if there's
352 // no connection? 374 // no connection?
353 if (output_queue_.empty()) 375 if (output_queue_.empty())
354 return true; 376 return true;
355 377
356 if (pipe_ == -1) 378 if (pipe_ == -1)
357 return false; 379 return false;
358 380
359 // Write out all the messages we can till the write blocks or there are no 381 // Write out all the messages we can till the write blocks or there are no
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 // Only the Hello message sends the file descriptor with the message. 434 // Only the Hello message sends the file descriptor with the message.
413 // Subsequently, we can send file descriptors on the dedicated 435 // Subsequently, we can send file descriptors on the dedicated
414 // fd_pipe_ which makes Seccomp sandbox operation more efficient. 436 // fd_pipe_ which makes Seccomp sandbox operation more efficient.
415 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 }; 437 struct iovec fd_pipe_iov = { const_cast<char *>(""), 1 };
416 msgh.msg_iov = &fd_pipe_iov; 438 msgh.msg_iov = &fd_pipe_iov;
417 fd_written = fd_pipe_; 439 fd_written = fd_pipe_;
418 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT)); 440 bytes_written = HANDLE_EINTR(sendmsg(fd_pipe_, &msgh, MSG_DONTWAIT));
419 msgh.msg_iov = &iov; 441 msgh.msg_iov = &iov;
420 msgh.msg_controllen = 0; 442 msgh.msg_controllen = 0;
421 if (bytes_written > 0) { 443 if (bytes_written > 0) {
422 msg->file_descriptor_set()->CommitAll(); 444 CloseFileDescriptors(msg);
423 } 445 }
424 } 446 }
425 #endif // IPC_USES_READWRITE 447 #endif // IPC_USES_READWRITE
426 } 448 }
427 449
428 if (bytes_written == 1) { 450 if (bytes_written == 1) {
429 fd_written = pipe_; 451 fd_written = pipe_;
430 #if defined(IPC_USES_READWRITE) 452 #if defined(IPC_USES_READWRITE)
431 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) { 453 if ((mode_ & MODE_CLIENT_FLAG) && IsHelloMessage(*msg)) {
432 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U); 454 DCHECK_EQ(msg->file_descriptor_set()->size(), 1U);
433 } 455 }
434 if (!msgh.msg_controllen) { 456 if (!msgh.msg_controllen) {
435 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write)); 457 bytes_written = HANDLE_EINTR(write(pipe_, out_bytes, amt_to_write));
436 } else 458 } else
437 #endif // IPC_USES_READWRITE 459 #endif // IPC_USES_READWRITE
438 { 460 {
439 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT)); 461 bytes_written = HANDLE_EINTR(sendmsg(pipe_, &msgh, MSG_DONTWAIT));
440 } 462 }
441 } 463 }
442 if (bytes_written > 0) 464 if (bytes_written > 0)
443 msg->file_descriptor_set()->CommitAll(); 465 CloseFileDescriptors(msg);
444 466
445 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) { 467 if (bytes_written < 0 && !SocketWriteErrorIsRecoverable()) {
446 #if defined(OS_MACOSX) 468 #if defined(OS_MACOSX)
447 // On OSX writing to a pipe with no listener returns EPERM. 469 // On OSX writing to a pipe with no listener returns EPERM.
448 if (errno == EPERM) { 470 if (errno == EPERM) {
449 Close(); 471 Close();
450 return false; 472 return false;
451 } 473 }
452 #endif // OS_MACOSX 474 #endif // OS_MACOSX
453 if (errno == EPIPE) { 475 if (errno == EPIPE) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 #endif // IPC_USES_READWRITE 590 #endif // IPC_USES_READWRITE
569 591
570 while (!output_queue_.empty()) { 592 while (!output_queue_.empty()) {
571 Message* m = output_queue_.front(); 593 Message* m = output_queue_.front();
572 output_queue_.pop(); 594 output_queue_.pop();
573 delete m; 595 delete m;
574 } 596 }
575 597
576 // Close any outstanding, received file descriptors. 598 // Close any outstanding, received file descriptors.
577 ClearInputFDs(); 599 ClearInputFDs();
600
601 #if defined(OS_MACOSX)
602 // Clear any outstanding, sent file descriptors.
603 for (std::set<int>::iterator i = fds_to_close_.begin();
604 i != fds_to_close_.end();
605 ++i) {
606 if (HANDLE_EINTR(close(*i)) < 0)
607 PLOG(ERROR) << "close";
608 }
609 fds_to_close_.clear();
610 #endif
578 } 611 }
579 612
580 // static 613 // static
581 bool Channel::ChannelImpl::IsNamedServerInitialized( 614 bool Channel::ChannelImpl::IsNamedServerInitialized(
582 const std::string& channel_id) { 615 const std::string& channel_id) {
583 return base::PathExists(base::FilePath(channel_id)); 616 return base::PathExists(base::FilePath(channel_id));
584 } 617 }
585 618
586 #if defined(OS_LINUX) 619 #if defined(OS_LINUX)
587 // static 620 // static
588 void Channel::ChannelImpl::SetGlobalPid(int pid) { 621 void Channel::ChannelImpl::SetGlobalPid(int pid) {
589 global_pid_ = pid; 622 global_pid_ = pid;
590 } 623 }
591 #endif // OS_LINUX 624 #endif // OS_LINUX
592 625
593 // Called by libevent when we can read from the pipe without blocking. 626 // Called by libevent when we can read from the pipe without blocking.
594 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { 627 void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) {
595 bool send_server_hello_msg = false;
596 if (fd == server_listen_pipe_) { 628 if (fd == server_listen_pipe_) {
597 int new_pipe = 0; 629 int new_pipe = 0;
598 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe) || 630 if (!ServerAcceptConnection(server_listen_pipe_, &new_pipe) ||
599 new_pipe < 0) { 631 new_pipe < 0) {
600 Close(); 632 Close();
601 listener()->OnChannelListenError(); 633 listener()->OnChannelListenError();
602 } 634 }
603 635
604 if (pipe_ != -1) { 636 if (pipe_ != -1) {
605 // We already have a connection. We only handle one at a time. 637 // We already have a connection. We only handle one at a time.
(...skipping 18 matching lines...) Expand all
624 if (client_euid != geteuid()) { 656 if (client_euid != geteuid()) {
625 DLOG(WARNING) << "Client euid is not authorised"; 657 DLOG(WARNING) << "Client euid is not authorised";
626 ResetToAcceptingConnectionState(); 658 ResetToAcceptingConnectionState();
627 return; 659 return;
628 } 660 }
629 } 661 }
630 662
631 if (!AcceptConnection()) { 663 if (!AcceptConnection()) {
632 NOTREACHED() << "AcceptConnection should not fail on server"; 664 NOTREACHED() << "AcceptConnection should not fail on server";
633 } 665 }
634 send_server_hello_msg = true;
635 waiting_connect_ = false; 666 waiting_connect_ = false;
636 } else if (fd == pipe_) { 667 } else if (fd == pipe_) {
637 if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) { 668 if (waiting_connect_ && (mode_ & MODE_SERVER_FLAG)) {
638 send_server_hello_msg = true;
639 waiting_connect_ = false; 669 waiting_connect_ = false;
640 } 670 }
641 if (!ProcessIncomingMessages()) { 671 if (!ProcessIncomingMessages()) {
642 // ClosePipeOnError may delete this object, so we mustn't call 672 // ClosePipeOnError may delete this object, so we mustn't call
643 // ProcessOutgoingMessages. 673 // ProcessOutgoingMessages.
644 send_server_hello_msg = false;
645 ClosePipeOnError(); 674 ClosePipeOnError();
675 return;
646 } 676 }
647 } else { 677 } else {
648 NOTREACHED() << "Unknown pipe " << fd; 678 NOTREACHED() << "Unknown pipe " << fd;
649 } 679 }
650 680
651 // If we're a server and handshaking, then we want to make sure that we 681 // If we're a server and handshaking, then we want to make sure that we
652 // only send our handshake message after we've processed the client's. 682 // only send our handshake message after we've processed the client's.
653 // This gives us a chance to kill the client if the incoming handshake 683 // This gives us a chance to kill the client if the incoming handshake
654 // is invalid. 684 // is invalid. This also flushes any closefd messagse.
655 if (send_server_hello_msg) { 685 if (!is_blocked_on_write_) {
656 ProcessOutgoingMessages(); 686 ProcessOutgoingMessages();
657 } 687 }
658 } 688 }
659 689
660 // Called by libevent when we can write to the pipe without blocking. 690 // Called by libevent when we can write to the pipe without blocking.
661 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) { 691 void Channel::ChannelImpl::OnFileCanWriteWithoutBlocking(int fd) {
662 DCHECK_EQ(pipe_, fd); 692 DCHECK_EQ(pipe_, fd);
663 is_blocked_on_write_ = false; 693 is_blocked_on_write_ = false;
664 if (!ProcessOutgoingMessages()) { 694 if (!ProcessOutgoingMessages()) {
665 ClosePipeOnError(); 695 ClosePipeOnError();
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 } 925 }
896 926
897 void Channel::ChannelImpl::ClearInputFDs() { 927 void Channel::ChannelImpl::ClearInputFDs() {
898 for (size_t i = 0; i < input_fds_.size(); ++i) { 928 for (size_t i = 0; i < input_fds_.size(); ++i) {
899 if (HANDLE_EINTR(close(input_fds_[i])) < 0) 929 if (HANDLE_EINTR(close(input_fds_[i])) < 0)
900 PLOG(ERROR) << "close "; 930 PLOG(ERROR) << "close ";
901 } 931 }
902 input_fds_.clear(); 932 input_fds_.clear();
903 } 933 }
904 934
905 void Channel::ChannelImpl::HandleHelloMessage(const Message& msg) { 935 void Channel::ChannelImpl::QueueCloseFDMessage(int fd, int hops) {
936 switch (hops) {
937 case 1:
938 case 2: {
939 // Create the message
940 scoped_ptr<Message> msg(new Message(MSG_ROUTING_NONE,
941 CLOSE_FD_MESSAGE_TYPE,
942 IPC::Message::PRIORITY_NORMAL));
943 if (!msg->WriteInt(hops - 1) || !msg->WriteInt(fd)) {
944 NOTREACHED() << "Unable to pickle close fd.";
945 }
946 // Send(msg.release());
947 output_queue_.push(msg.release());
948 break;
949 }
950
951 default:
952 NOTREACHED();
953 break;
954 }
955 }
956
957 void Channel::ChannelImpl::HandleInternalMessage(const Message& msg) {
906 // The Hello message contains only the process id. 958 // The Hello message contains only the process id.
907 PickleIterator iter(msg); 959 PickleIterator iter(msg);
908 int pid; 960
909 if (!msg.ReadInt(&iter, &pid)) 961 switch (msg.type()) {
910 NOTREACHED(); 962 default:
963 NOTREACHED();
964 break;
965
966 case Channel::HELLO_MESSAGE_TYPE:
967 int pid;
968 if (!msg.ReadInt(&iter, &pid))
969 NOTREACHED();
911 970
912 #if defined(IPC_USES_READWRITE) 971 #if defined(IPC_USES_READWRITE)
913 if (mode_ & MODE_SERVER_FLAG) { 972 if (mode_ & MODE_SERVER_FLAG) {
914 // With IPC_USES_READWRITE, the Hello message from the client to the 973 // With IPC_USES_READWRITE, the Hello message from the client to the
915 // server also contains the fd_pipe_, which will be used for all 974 // server also contains the fd_pipe_, which will be used for all
916 // subsequent file descriptor passing. 975 // subsequent file descriptor passing.
917 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U); 976 DCHECK_EQ(msg.file_descriptor_set()->size(), 1U);
918 base::FileDescriptor descriptor; 977 base::FileDescriptor descriptor;
919 if (!msg.ReadFileDescriptor(&iter, &descriptor)) { 978 if (!msg.ReadFileDescriptor(&iter, &descriptor)) {
920 NOTREACHED(); 979 NOTREACHED();
921 } 980 }
922 fd_pipe_ = descriptor.fd; 981 fd_pipe_ = descriptor.fd;
923 CHECK(descriptor.auto_close); 982 CHECK(descriptor.auto_close);
983 }
984 #endif // IPC_USES_READWRITE
985 peer_pid_ = pid;
986 listener()->OnChannelConnected(pid);
987 break;
988
989 #if defined(OS_MACOSX)
990 case Channel::CLOSE_FD_MESSAGE_TYPE:
991 int fd, hops;
992 if (!msg.ReadInt(&iter, &hops))
993 NOTREACHED();
994 if (!msg.ReadInt(&iter, &fd))
995 NOTREACHED();
996 if (hops == 0) {
997 if (fds_to_close_.erase(fd) > 0) {
998 if (HANDLE_EINTR(close(fd)) < 0)
999 PLOG(ERROR) << "close";
1000 } else {
1001 NOTREACHED();
1002 }
1003 } else {
1004 QueueCloseFDMessage(fd, hops);
1005 }
1006 break;
1007 #endif
924 } 1008 }
925 #endif // IPC_USES_READWRITE
926 peer_pid_ = pid;
927 listener()->OnChannelConnected(pid);
928 } 1009 }
929 1010
930 void Channel::ChannelImpl::Close() { 1011 void Channel::ChannelImpl::Close() {
931 // Close can be called multiple time, so we need to make sure we're 1012 // Close can be called multiple time, so we need to make sure we're
932 // idempotent. 1013 // idempotent.
933 1014
934 ResetToAcceptingConnectionState(); 1015 ResetToAcceptingConnectionState();
935 1016
936 if (must_unlink_) { 1017 if (must_unlink_) {
937 unlink(pipe_name_.c_str()); 1018 unlink(pipe_name_.c_str());
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1019 1100
1020 1101
1021 #if defined(OS_LINUX) 1102 #if defined(OS_LINUX)
1022 // static 1103 // static
1023 void Channel::SetGlobalPid(int pid) { 1104 void Channel::SetGlobalPid(int pid) {
1024 ChannelImpl::SetGlobalPid(pid); 1105 ChannelImpl::SetGlobalPid(pid);
1025 } 1106 }
1026 #endif // OS_LINUX 1107 #endif // OS_LINUX
1027 1108
1028 } // namespace IPC 1109 } // namespace IPC
OLDNEW
« ipc/ipc_channel.h ('K') | « ipc/ipc_channel_posix.h ('k') | ipc/ipc_channel_reader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698