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

Unified Diff: chromeos/process_proxy/process_output_watcher.cc

Issue 1258193002: User MessageLoopForIO::WatchFileDescriptor in proces_output_watcher (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 5 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: chromeos/process_proxy/process_output_watcher.cc
diff --git a/chromeos/process_proxy/process_output_watcher.cc b/chromeos/process_proxy/process_output_watcher.cc
index 17c1c9459a77dea6d4cb816493e2a2c4050f643b..92868c0e931a2622b2458c6d608f9913b8bb251a 100644
--- a/chromeos/process_proxy/process_output_watcher.cc
+++ b/chromeos/process_proxy/process_output_watcher.cc
@@ -4,35 +4,20 @@
#include "chromeos/process_proxy/process_output_watcher.h"
-#include <sys/ioctl.h>
-#include <sys/select.h>
-#include <unistd.h>
-
#include <algorithm>
#include <cstdio>
#include <cstring>
-
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
+#include "base/single_thread_task_runner.h"
#include "base/third_party/icu/icu_utf.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
namespace {
-void InitReadFdSet(int out_fd, int stop_fd, fd_set* set) {
- FD_ZERO(set);
- if (out_fd != -1)
- FD_SET(out_fd, set);
- FD_SET(stop_fd, set);
-}
-
-void CloseFd(int* fd) {
- if (*fd >= 0) {
- if (IGNORE_EINTR(close(*fd)) != 0)
- DPLOG(WARNING) << "close fd " << *fd << " failed.";
- }
- *fd = -1;
-}
-
// Gets byte size for a UTF8 character given it's leading byte. The character
// size is encoded as number of leading '1' bits in the character's leading
// byte. If the most significant bit is '0', the character is a valid ASCII
@@ -55,87 +40,77 @@ size_t UTF8SizeFromLeadingByte(uint8 leading_byte) {
namespace chromeos {
-// static
-bool ProcessOutputWatcher::VerifyFileDescriptor(int fd) {
- return (fd >= 0) && (fd < FD_SETSIZE);
-}
-
ProcessOutputWatcher::ProcessOutputWatcher(
int out_fd,
- int stop_fd,
const ProcessOutputCallback& callback)
: read_buffer_size_(0),
- out_fd_(out_fd),
- stop_fd_(stop_fd),
- on_read_callback_(callback) {
- CHECK(VerifyFileDescriptor(out_fd_));
- CHECK(VerifyFileDescriptor(stop_fd_));
- max_fd_ = std::max(out_fd_, stop_fd_);
+ process_output_file_(out_fd),
+ on_read_callback_(callback),
+ weak_factory_(this) {
+ CHECK_GE(out_fd, 0);
// We want to be sure we will be able to add 0 at the end of the input, so -1.
read_buffer_capacity_ = arraysize(read_buffer_) - 1;
}
+ProcessOutputWatcher::~ProcessOutputWatcher() {}
+
void ProcessOutputWatcher::Start() {
WatchProcessOutput();
- OnStop();
-}
-
-ProcessOutputWatcher::~ProcessOutputWatcher() {
- CloseFd(&out_fd_);
- CloseFd(&stop_fd_);
}
-void ProcessOutputWatcher::WatchProcessOutput() {
- while (true) {
- // This has to be reset with every watch cycle.
- fd_set rfds;
- DCHECK_GE(stop_fd_, 0);
- InitReadFdSet(out_fd_, stop_fd_, &rfds);
-
- int select_result =
- HANDLE_EINTR(select(max_fd_ + 1, &rfds, NULL, NULL, NULL));
+void ProcessOutputWatcher::OnFileCanReadWithoutBlocking(int fd) {
+ DCHECK_EQ(process_output_file_.GetPlatformFile(), fd);
- if (select_result < 0) {
- DPLOG(WARNING) << "select failed";
- return;
- }
+ output_file_watcher_.StopWatchingFileDescriptor();
+ ReadFromFd(fd);
+}
- // Check if we were stopped.
- if (FD_ISSET(stop_fd_, &rfds)) {
- return;
- }
+void ProcessOutputWatcher::OnFileCanWriteWithoutBlocking(int fd) {
+ NOTREACHED();
+}
- if (out_fd_ != -1 && FD_ISSET(out_fd_, &rfds)) {
- ReadFromFd(PROCESS_OUTPUT_TYPE_OUT, &out_fd_);
- }
- }
+void ProcessOutputWatcher::WatchProcessOutput() {
+ base::MessageLoopForIO::current()->WatchFileDescriptor(
+ process_output_file_.GetPlatformFile(), false,
+ base::MessageLoopForIO::WATCH_READ, &output_file_watcher_, this);
}
-void ProcessOutputWatcher::ReadFromFd(ProcessOutputType type, int* fd) {
+void ProcessOutputWatcher::ReadFromFd(int fd) {
// We don't want to necessary read pipe until it is empty so we don't starve
// other streams in case data is written faster than we read it. If there is
// more than read_buffer_size_ bytes in pipe, it will be read in the next
// iteration.
DCHECK_GT(read_buffer_capacity_, read_buffer_size_);
ssize_t bytes_read =
- HANDLE_EINTR(read(*fd,
- &read_buffer_[read_buffer_size_],
+ HANDLE_EINTR(read(fd, &read_buffer_[read_buffer_size_],
read_buffer_capacity_ - read_buffer_size_));
+
+ if (bytes_read > 0) {
+ ReportOutput(PROCESS_OUTPUT_TYPE_OUT, bytes_read);
+
+ // Delay next read to make the process less likely to flood IPC channel
+ // when output is reported to terminal extension via terminalPrivate API
+ // (which is the only client of this code).
+ // TODO(tbarzic): Properly fix this!! Provide a mechanism for clients to
+ // ack reported output and continue watching the process when ack is
+ // received. https://crbug.com/398901
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::Bind(&ProcessOutputWatcher::WatchProcessOutput,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(10));
+
+ return;
+ }
+
if (bytes_read < 0)
DPLOG(WARNING) << "read from buffer failed";
- if (bytes_read > 0)
- ReportOutput(type, bytes_read);
-
// If there is nothing on the output the watched process has exited (slave end
// of pty is closed).
- if (bytes_read <= 0) {
- // Slave pseudo terminal has been closed, we won't need master fd anymore.
- CloseFd(fd);
+ on_read_callback_.Run(PROCESS_OUTPUT_TYPE_EXIT, "");
- // We have lost contact with the process, so report it.
- on_read_callback_.Run(PROCESS_OUTPUT_TYPE_EXIT, "");
- }
+ // Cancel pending |WatchProcessOutput| calls.
+ weak_factory_.InvalidateWeakPtrs();
}
size_t ProcessOutputWatcher::OutputSizeWithoutIncompleteUTF8() {
@@ -191,8 +166,4 @@ void ProcessOutputWatcher::ReportOutput(ProcessOutputType type,
read_buffer_size_ -= output_to_report;
}
-void ProcessOutputWatcher::OnStop() {
- delete this;
-}
-
} // namespace chromeos
« no previous file with comments | « chromeos/process_proxy/process_output_watcher.h ('k') | chromeos/process_proxy/process_output_watcher_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698