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

Side by Side Diff: chrome/browser/chromeos/process_proxy/process_output_watcher.cc

Issue 12433023: Move chrome/browser/chromeos/process_proxy to chromeos (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 9 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/process_proxy/process_output_watcher.h"
6
7 #include <algorithm>
8 #include <cstdio>
9 #include <cstring>
10
11 #include <sys/ioctl.h>
12 #include <sys/select.h>
13 #include <unistd.h>
14
15 #include "base/logging.h"
16 #include "base/posix/eintr_wrapper.h"
17
18 namespace {
19
20 void InitReadFdSet(int out_fd, int stop_fd, fd_set* set) {
21 FD_ZERO(set);
22 if (out_fd != -1)
23 FD_SET(out_fd, set);
24 FD_SET(stop_fd, set);
25 }
26
27 void CloseFd(int* fd) {
28 if (*fd >= 0) {
29 if (HANDLE_EINTR(close(*fd)) != 0)
30 DPLOG(WARNING) << "close fd " << *fd << " failed.";
31 }
32 *fd = -1;
33 }
34
35 } // namespace
36
37 ProcessOutputWatcher::ProcessOutputWatcher(int out_fd, int stop_fd,
38 const ProcessOutputCallback& callback)
39 : out_fd_(out_fd),
40 stop_fd_(stop_fd),
41 on_read_callback_(callback) {
42 VerifyFileDescriptor(out_fd_);
43 VerifyFileDescriptor(stop_fd_);
44 max_fd_ = std::max(out_fd_, stop_fd_);
45 // We want to be sure we will be able to add 0 at the end of the input, so -1.
46 read_buffer_size_ = arraysize(read_buffer_) - 1;
47 }
48
49 void ProcessOutputWatcher::Start() {
50 WatchProcessOutput();
51 OnStop();
52 }
53
54 ProcessOutputWatcher::~ProcessOutputWatcher() {
55 CloseFd(&out_fd_);
56 CloseFd(&stop_fd_);
57 }
58
59 void ProcessOutputWatcher::WatchProcessOutput() {
60 while (true) {
61 // This has to be reset with every watch cycle.
62 fd_set rfds;
63 DCHECK(stop_fd_ >= 0);
64 InitReadFdSet(out_fd_, stop_fd_, &rfds);
65
66 int select_result =
67 HANDLE_EINTR(select(max_fd_ + 1, &rfds, NULL, NULL, NULL));
68
69 if (select_result < 0) {
70 DPLOG(WARNING) << "select failed";
71 return;
72 }
73
74 // Check if we were stopped.
75 if (FD_ISSET(stop_fd_, &rfds)) {
76 return;
77 }
78
79 if (out_fd_ != -1 && FD_ISSET(out_fd_, &rfds)) {
80 ReadFromFd(PROCESS_OUTPUT_TYPE_OUT, &out_fd_);
81 }
82 }
83 }
84
85 void ProcessOutputWatcher::VerifyFileDescriptor(int fd) {
86 CHECK_LE(0, fd);
87 CHECK_GT(FD_SETSIZE, fd);
88 }
89
90 void ProcessOutputWatcher::ReadFromFd(ProcessOutputType type, int* fd) {
91 // We don't want to necessary read pipe until it is empty so we don't starve
92 // other streams in case data is written faster than we read it. If there is
93 // more than read_buffer_size_ bytes in pipe, it will be read in the next
94 // iteration.
95 ssize_t bytes_read = HANDLE_EINTR(read(*fd, read_buffer_, read_buffer_size_));
96 if (bytes_read < 0)
97 DPLOG(WARNING) << "read from buffer failed";
98
99 if (bytes_read > 0) {
100 on_read_callback_.Run(type, std::string(read_buffer_, bytes_read));
101 }
102
103 // If there is nothing on the output the watched process has exited (slave end
104 // of pty is closed).
105 if (bytes_read <= 0) {
106 // Slave pseudo terminal has been closed, we won't need master fd anymore.
107 CloseFd(fd);
108
109 // We have lost contact with the process, so report it.
110 on_read_callback_.Run(PROCESS_OUTPUT_TYPE_EXIT, "");
111 }
112 }
113
114 void ProcessOutputWatcher::OnStop() {
115 delete this;
116 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698