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

Side by Side Diff: chrome/browser/process_singleton_linux.cc

Issue 8571019: Fix linux ProcessSingleton invalid message handling infinite log spam. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: re-add FinishWithACK comment Created 9 years, 1 month 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
« 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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 // On Linux, when the user tries to launch a second copy of chrome, we check 5 // On Linux, when the user tries to launch a second copy of chrome, we check
6 // for a socket in the user's profile directory. If the socket file is open we 6 // for a socket in the user's profile directory. If the socket file is open we
7 // send a message to the first chrome browser process with the current 7 // send a message to the first chrome browser process with the current
8 // directory and second process command line flags. The second process then 8 // directory and second process command line flags. The second process then
9 // exits. 9 // exits.
10 // 10 //
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 #include <sys/types.h> 52 #include <sys/types.h>
53 #include <sys/un.h> 53 #include <sys/un.h>
54 #include <unistd.h> 54 #include <unistd.h>
55 55
56 #include <cstring> 56 #include <cstring>
57 #include <set> 57 #include <set>
58 #include <string> 58 #include <string>
59 59
60 #include "base/base_paths.h" 60 #include "base/base_paths.h"
61 #include "base/basictypes.h" 61 #include "base/basictypes.h"
62 #include "base/bind.h"
62 #include "base/command_line.h" 63 #include "base/command_line.h"
63 #include "base/eintr_wrapper.h" 64 #include "base/eintr_wrapper.h"
64 #include "base/file_path.h" 65 #include "base/file_path.h"
65 #include "base/file_util.h" 66 #include "base/file_util.h"
66 #include "base/logging.h" 67 #include "base/logging.h"
67 #include "base/message_loop.h" 68 #include "base/message_loop.h"
68 #include "base/path_service.h" 69 #include "base/path_service.h"
69 #include "base/process_util.h" 70 #include "base/process_util.h"
70 #include "base/rand_util.h" 71 #include "base/rand_util.h"
71 #include "base/safe_strerror_posix.h" 72 #include "base/safe_strerror_posix.h"
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
454 } // namespace 455 } // namespace
455 456
456 /////////////////////////////////////////////////////////////////////////////// 457 ///////////////////////////////////////////////////////////////////////////////
457 // ProcessSingleton::LinuxWatcher 458 // ProcessSingleton::LinuxWatcher
458 // A helper class for a Linux specific implementation of the process singleton. 459 // A helper class for a Linux specific implementation of the process singleton.
459 // This class sets up a listener on the singleton socket and handles parsing 460 // This class sets up a listener on the singleton socket and handles parsing
460 // messages that come in on the singleton socket. 461 // messages that come in on the singleton socket.
461 class ProcessSingleton::LinuxWatcher 462 class ProcessSingleton::LinuxWatcher
462 : public MessageLoopForIO::Watcher, 463 : public MessageLoopForIO::Watcher,
463 public MessageLoop::DestructionObserver, 464 public MessageLoop::DestructionObserver,
464 public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher> { 465 public base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher,
466 BrowserThread::DeleteOnIOThread> {
465 public: 467 public:
466 // A helper class to read message from an established socket. 468 // A helper class to read message from an established socket.
467 class SocketReader : public MessageLoopForIO::Watcher { 469 class SocketReader : public MessageLoopForIO::Watcher {
468 public: 470 public:
469 SocketReader(ProcessSingleton::LinuxWatcher* parent, 471 SocketReader(ProcessSingleton::LinuxWatcher* parent,
470 MessageLoop* ui_message_loop, 472 MessageLoop* ui_message_loop,
471 int fd) 473 int fd)
472 : parent_(parent), 474 : parent_(parent),
473 ui_message_loop_(ui_message_loop), 475 ui_message_loop_(ui_message_loop),
474 fd_(fd), 476 fd_(fd),
475 bytes_read_(0) { 477 bytes_read_(0) {
478 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
476 // Wait for reads. 479 // Wait for reads.
477 MessageLoopForIO::current()->WatchFileDescriptor( 480 MessageLoopForIO::current()->WatchFileDescriptor(
478 fd, true, MessageLoopForIO::WATCH_READ, &fd_reader_, this); 481 fd, true, MessageLoopForIO::WATCH_READ, &fd_reader_, this);
482 // If we haven't completed in a reasonable amount of time, give up.
479 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds), 483 timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(kTimeoutInSeconds),
480 this, &SocketReader::OnTimerExpiry); 484 this, &SocketReader::CleanupAndDeleteSelf);
481 } 485 }
482 486
483 virtual ~SocketReader() { 487 virtual ~SocketReader() {
484 CloseSocket(fd_); 488 CloseSocket(fd_);
485 } 489 }
486 490
487 // MessageLoopForIO::Watcher impl. 491 // MessageLoopForIO::Watcher impl.
488 virtual void OnFileCanReadWithoutBlocking(int fd); 492 virtual void OnFileCanReadWithoutBlocking(int fd);
489 virtual void OnFileCanWriteWithoutBlocking(int fd) { 493 virtual void OnFileCanWriteWithoutBlocking(int fd) {
490 // SocketReader only watches for accept (read) events. 494 // SocketReader only watches for accept (read) events.
491 NOTREACHED(); 495 NOTREACHED();
492 } 496 }
493 497
494 // Finish handling the incoming message by optionally sending back an ACK 498 // Finish handling the incoming message by optionally sending back an ACK
495 // message and removing this SocketReader. 499 // message and removing this SocketReader.
496 void FinishWithACK(const char *message, size_t length); 500 void FinishWithACK(const char *message, size_t length);
497 501
498 private: 502 private:
499 // If we haven't completed in a reasonable amount of time, give up. 503 void CleanupAndDeleteSelf() {
500 void OnTimerExpiry() { 504 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
505
501 parent_->RemoveSocketReader(this); 506 parent_->RemoveSocketReader(this);
502 // We're deleted beyond this point. 507 // We're deleted beyond this point.
503 } 508 }
504 509
505 MessageLoopForIO::FileDescriptorWatcher fd_reader_; 510 MessageLoopForIO::FileDescriptorWatcher fd_reader_;
506 511
507 // The ProcessSingleton::LinuxWatcher that owns us. 512 // The ProcessSingleton::LinuxWatcher that owns us.
508 ProcessSingleton::LinuxWatcher* const parent_; 513 ProcessSingleton::LinuxWatcher* const parent_;
509 514
510 // A reference to the UI message loop. 515 // A reference to the UI message loop.
(...skipping 22 matching lines...) Expand all
533 538
534 // Start listening for connections on the socket. This method should be 539 // Start listening for connections on the socket. This method should be
535 // called from the IO thread. 540 // called from the IO thread.
536 void StartListening(int socket); 541 void StartListening(int socket);
537 542
538 // This method determines if we should use the same process and if we should, 543 // This method determines if we should use the same process and if we should,
539 // opens a new browser tab. This runs on the UI thread. 544 // opens a new browser tab. This runs on the UI thread.
540 // |reader| is for sending back ACK message. 545 // |reader| is for sending back ACK message.
541 void HandleMessage(const std::string& current_dir, 546 void HandleMessage(const std::string& current_dir,
542 const std::vector<std::string>& argv, 547 const std::vector<std::string>& argv,
543 SocketReader *reader); 548 SocketReader* reader);
544 549
545 // MessageLoopForIO::Watcher impl. These run on the IO thread. 550 // MessageLoopForIO::Watcher impl. These run on the IO thread.
546 virtual void OnFileCanReadWithoutBlocking(int fd); 551 virtual void OnFileCanReadWithoutBlocking(int fd);
547 virtual void OnFileCanWriteWithoutBlocking(int fd) { 552 virtual void OnFileCanWriteWithoutBlocking(int fd) {
548 // ProcessSingleton only watches for accept (read) events. 553 // ProcessSingleton only watches for accept (read) events.
549 NOTREACHED(); 554 NOTREACHED();
550 } 555 }
551 556
552 // MessageLoop::DestructionObserver 557 // MessageLoop::DestructionObserver
553 virtual void WillDestroyCurrentMessageLoop() { 558 virtual void WillDestroyCurrentMessageLoop() {
554 fd_watcher_.StopWatchingFileDescriptor(); 559 fd_watcher_.StopWatchingFileDescriptor();
555 } 560 }
556 561
557 private: 562 private:
558 friend class base::RefCountedThreadSafe<ProcessSingleton::LinuxWatcher>; 563 friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
564 friend class DeleteTask<ProcessSingleton::LinuxWatcher>;
559 565
560 virtual ~LinuxWatcher() { 566 virtual ~LinuxWatcher() {
567 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
561 STLDeleteElements(&readers_); 568 STLDeleteElements(&readers_);
562 } 569 }
563 570
564 // Removes and deletes the SocketReader. 571 // Removes and deletes the SocketReader.
565 void RemoveSocketReader(SocketReader* reader); 572 void RemoveSocketReader(SocketReader* reader);
566 573
567 MessageLoopForIO::FileDescriptorWatcher fd_watcher_; 574 MessageLoopForIO::FileDescriptorWatcher fd_watcher_;
568 575
569 // A reference to the UI message loop (i.e., the message loop we were 576 // A reference to the UI message loop (i.e., the message loop we were
570 // constructed on). 577 // constructed on).
571 MessageLoop* ui_message_loop_; 578 MessageLoop* ui_message_loop_;
572 579
573 // The ProcessSingleton that owns us. 580 // The ProcessSingleton that owns us.
574 ProcessSingleton* const parent_; 581 ProcessSingleton* const parent_;
575 582
576 std::set<SocketReader*> readers_; 583 std::set<SocketReader*> readers_;
577 584
578 DISALLOW_COPY_AND_ASSIGN(LinuxWatcher); 585 DISALLOW_COPY_AND_ASSIGN(LinuxWatcher);
579 }; 586 };
580 587
581 void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) { 588 void ProcessSingleton::LinuxWatcher::OnFileCanReadWithoutBlocking(int fd) {
589 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
582 // Accepting incoming client. 590 // Accepting incoming client.
583 sockaddr_un from; 591 sockaddr_un from;
584 socklen_t from_len = sizeof(from); 592 socklen_t from_len = sizeof(from);
585 int connection_socket = HANDLE_EINTR(accept( 593 int connection_socket = HANDLE_EINTR(accept(
586 fd, reinterpret_cast<sockaddr*>(&from), &from_len)); 594 fd, reinterpret_cast<sockaddr*>(&from), &from_len));
587 if (-1 == connection_socket) { 595 if (-1 == connection_socket) {
588 PLOG(ERROR) << "accept() failed"; 596 PLOG(ERROR) << "accept() failed";
589 return; 597 return;
590 } 598 }
591 int rv = SetNonBlocking(connection_socket); 599 int rv = SetNonBlocking(connection_socket);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
657 BrowserInit::ProcessCommandLine(parsed_command_line, current_dir_file_path, 665 BrowserInit::ProcessCommandLine(parsed_command_line, current_dir_file_path,
658 false /* not process startup */, profile, 666 false /* not process startup */, profile,
659 NULL); 667 NULL);
660 } 668 }
661 669
662 // Send back "ACK" message to prevent the client process from starting up. 670 // Send back "ACK" message to prevent the client process from starting up.
663 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1); 671 reader->FinishWithACK(kACKToken, arraysize(kACKToken) - 1);
664 } 672 }
665 673
666 void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) { 674 void ProcessSingleton::LinuxWatcher::RemoveSocketReader(SocketReader* reader) {
675 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
667 DCHECK(reader); 676 DCHECK(reader);
668 readers_.erase(reader); 677 readers_.erase(reader);
669 delete reader; 678 delete reader;
670 } 679 }
671 680
672 /////////////////////////////////////////////////////////////////////////////// 681 ///////////////////////////////////////////////////////////////////////////////
673 // ProcessSingleton::LinuxWatcher::SocketReader 682 // ProcessSingleton::LinuxWatcher::SocketReader
674 // 683 //
675 684
676 void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking( 685 void ProcessSingleton::LinuxWatcher::SocketReader::OnFileCanReadWithoutBlocking(
677 int fd) { 686 int fd) {
687 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
678 DCHECK_EQ(fd, fd_); 688 DCHECK_EQ(fd, fd_);
679 while (bytes_read_ < sizeof(buf_)) { 689 while (bytes_read_ < sizeof(buf_)) {
680 ssize_t rv = HANDLE_EINTR( 690 ssize_t rv = HANDLE_EINTR(
681 read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_)); 691 read(fd, buf_ + bytes_read_, sizeof(buf_) - bytes_read_));
682 if (rv < 0) { 692 if (rv < 0) {
683 if (errno != EAGAIN && errno != EWOULDBLOCK) { 693 if (errno != EAGAIN && errno != EWOULDBLOCK) {
684 PLOG(ERROR) << "read() failed"; 694 PLOG(ERROR) << "read() failed";
685 CloseSocket(fd); 695 CloseSocket(fd);
686 return; 696 return;
687 } else { 697 } else {
688 // It would block, so we just return and continue to watch for the next 698 // It would block, so we just return and continue to watch for the next
689 // opportunity to read. 699 // opportunity to read.
690 return; 700 return;
691 } 701 }
692 } else if (!rv) { 702 } else if (!rv) {
693 // No more data to read. It's time to process the message. 703 // No more data to read. It's time to process the message.
694 break; 704 break;
695 } else { 705 } else {
696 bytes_read_ += rv; 706 bytes_read_ += rv;
697 } 707 }
698 } 708 }
699 709
700 // Validate the message. The shortest message is kStartToken\0x\0x 710 // Validate the message. The shortest message is kStartToken\0x\0x
701 const size_t kMinMessageLength = arraysize(kStartToken) + 4; 711 const size_t kMinMessageLength = arraysize(kStartToken) + 4;
702 if (bytes_read_ < kMinMessageLength) { 712 if (bytes_read_ < kMinMessageLength) {
703 buf_[bytes_read_] = 0; 713 buf_[bytes_read_] = 0;
704 LOG(ERROR) << "Invalid socket message (wrong length):" << buf_; 714 LOG(ERROR) << "Invalid socket message (wrong length):" << buf_;
715 CleanupAndDeleteSelf();
705 return; 716 return;
706 } 717 }
707 718
708 std::string str(buf_, bytes_read_); 719 std::string str(buf_, bytes_read_);
709 std::vector<std::string> tokens; 720 std::vector<std::string> tokens;
710 base::SplitString(str, kTokenDelimiter, &tokens); 721 base::SplitString(str, kTokenDelimiter, &tokens);
711 722
712 if (tokens.size() < 3 || tokens[0] != kStartToken) { 723 if (tokens.size() < 3 || tokens[0] != kStartToken) {
713 LOG(ERROR) << "Wrong message format: " << str; 724 LOG(ERROR) << "Wrong message format: " << str;
725 CleanupAndDeleteSelf();
714 return; 726 return;
715 } 727 }
716 728
717 // Stop the expiration timer to prevent this SocketReader object from being 729 // Stop the expiration timer to prevent this SocketReader object from being
718 // terminated unexpectly. 730 // terminated unexpectly.
719 timer_.Stop(); 731 timer_.Stop();
720 732
721 std::string current_dir = tokens[1]; 733 std::string current_dir = tokens[1];
722 // Remove the first two tokens. The remaining tokens should be the command 734 // Remove the first two tokens. The remaining tokens should be the command
723 // line argv array. 735 // line argv array.
724 tokens.erase(tokens.begin()); 736 tokens.erase(tokens.begin());
725 tokens.erase(tokens.begin()); 737 tokens.erase(tokens.begin());
726 738
727 // Return to the UI thread to handle opening a new browser tab. 739 // Return to the UI thread to handle opening a new browser tab.
728 ui_message_loop_->PostTask(FROM_HERE, NewRunnableMethod( 740 ui_message_loop_->PostTask(FROM_HERE, base::Bind(
741 &ProcessSingleton::LinuxWatcher::HandleMessage,
729 parent_, 742 parent_,
730 &ProcessSingleton::LinuxWatcher::HandleMessage,
731 current_dir, 743 current_dir,
732 tokens, 744 tokens,
733 this)); 745 this));
734 fd_reader_.StopWatchingFileDescriptor(); 746 fd_reader_.StopWatchingFileDescriptor();
735 747
736 // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader 748 // LinuxWatcher::HandleMessage() is in charge of destroying this SocketReader
737 // object by invoking SocketReader::FinishWithACK(). 749 // object by invoking SocketReader::FinishWithACK().
738 } 750 }
739 751
740 void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK( 752 void ProcessSingleton::LinuxWatcher::SocketReader::FinishWithACK(
741 const char *message, size_t length) { 753 const char *message, size_t length) {
742 if (message && length) { 754 if (message && length) {
743 // Not necessary to care about the return value. 755 // Not necessary to care about the return value.
744 WriteToSocket(fd_, message, length); 756 WriteToSocket(fd_, message, length);
745 } 757 }
746 758
747 if (shutdown(fd_, SHUT_WR) < 0) 759 if (shutdown(fd_, SHUT_WR) < 0)
748 PLOG(ERROR) << "shutdown() failed"; 760 PLOG(ERROR) << "shutdown() failed";
749 761
750 parent_->RemoveSocketReader(this); 762 BrowserThread::PostTask(
751 // We are deleted beyond this point. 763 BrowserThread::IO,
764 FROM_HERE,
765 base::Bind(&ProcessSingleton::LinuxWatcher::RemoveSocketReader,
766 parent_,
767 this));
768 // We will be deleted once the posted RemoveSocketReader task runs.
752 } 769 }
753 770
754 /////////////////////////////////////////////////////////////////////////////// 771 ///////////////////////////////////////////////////////////////////////////////
755 // ProcessSingleton 772 // ProcessSingleton
756 // 773 //
757 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir) 774 ProcessSingleton::ProcessSingleton(const FilePath& user_data_dir)
758 : locked_(false), 775 : locked_(false),
759 foreground_window_(NULL), 776 foreground_window_(NULL),
760 ALLOW_THIS_IN_INITIALIZER_LIST(watcher_(new LinuxWatcher(this))) { 777 ALLOW_THIS_IN_INITIALIZER_LIST(watcher_(new LinuxWatcher(this))) {
761 socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename); 778 socket_path_ = user_data_dir.Append(chrome::kSingletonSocketFilename);
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 } 993 }
977 994
978 if (listen(sock, 5) < 0) 995 if (listen(sock, 5) < 0)
979 NOTREACHED() << "listen failed: " << safe_strerror(errno); 996 NOTREACHED() << "listen failed: " << safe_strerror(errno);
980 997
981 // Normally we would use BrowserThread, but the IO thread hasn't started yet. 998 // Normally we would use BrowserThread, but the IO thread hasn't started yet.
982 // Using g_browser_process, we start the thread so we can listen on the 999 // Using g_browser_process, we start the thread so we can listen on the
983 // socket. 1000 // socket.
984 MessageLoop* ml = g_browser_process->io_thread()->message_loop(); 1001 MessageLoop* ml = g_browser_process->io_thread()->message_loop();
985 DCHECK(ml); 1002 DCHECK(ml);
986 ml->PostTask(FROM_HERE, NewRunnableMethod( 1003 ml->PostTask(FROM_HERE, base::Bind(
1004 &ProcessSingleton::LinuxWatcher::StartListening,
987 watcher_.get(), 1005 watcher_.get(),
988 &ProcessSingleton::LinuxWatcher::StartListening,
989 sock)); 1006 sock));
990 1007
991 return true; 1008 return true;
992 } 1009 }
993 1010
994 void ProcessSingleton::Cleanup() { 1011 void ProcessSingleton::Cleanup() {
995 UnlinkPath(socket_path_); 1012 UnlinkPath(socket_path_);
996 UnlinkPath(cookie_path_); 1013 UnlinkPath(cookie_path_);
997 UnlinkPath(lock_path_); 1014 UnlinkPath(lock_path_);
998 } 1015 }
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