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

Side by Side Diff: native_client_sdk/src/libraries/nacl_io/mount_node_tty.cc

Issue 23498015: [NaCl SDK] Support non blocking TCP/UDP (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Added Fifo Tests Created 7 years, 3 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) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "nacl_io/mount_node_tty.h" 5 #include "nacl_io/mount_node_tty.h"
6 6
7 #include <assert.h> 7 #include <assert.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <signal.h> 9 #include <signal.h>
10 #include <stdio.h> 10 #include <stdio.h>
(...skipping 14 matching lines...) Expand all
25 #define IS_ECHOE CHECK_LFLAG(termios_, ECHOE) 25 #define IS_ECHOE CHECK_LFLAG(termios_, ECHOE)
26 #define IS_ECHONL CHECK_LFLAG(termios_, ECHONL) 26 #define IS_ECHONL CHECK_LFLAG(termios_, ECHONL)
27 #define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL) 27 #define IS_ECHOCTL CHECK_LFLAG(termios_, ECHOCTL)
28 #define IS_ICANON CHECK_LFLAG(termios_, ICANON) 28 #define IS_ICANON CHECK_LFLAG(termios_, ICANON)
29 29
30 #define DEFAULT_TTY_COLS 80 30 #define DEFAULT_TTY_COLS 80
31 #define DEFAULT_TTY_ROWS 30 31 #define DEFAULT_TTY_ROWS 30
32 32
33 namespace nacl_io { 33 namespace nacl_io {
34 34
35 MountNodeTty::MountNodeTty(Mount* mount) : MountNodeCharDevice(mount), 35
36 is_readable_(false), 36 MountNodeTty::MountNodeTty(Mount* mount)
37 did_resize_(false), 37 : MountNodeCharDevice(mount),
38 rows_(DEFAULT_TTY_ROWS), 38 emitter_(new EventEmitter),
39 cols_(DEFAULT_TTY_COLS) { 39 rows_(DEFAULT_TTY_ROWS),
40 cols_(DEFAULT_TTY_COLS) {
40 output_handler_.handler = NULL; 41 output_handler_.handler = NULL;
41 pthread_cond_init(&is_readable_cond_, NULL);
42 InitTermios(); 42 InitTermios();
43
44 // Output will never block
45 emitter_->RaiseEvents_Locked(POLLOUT);
43 } 46 }
44 47
45 void MountNodeTty::InitTermios() { 48 void MountNodeTty::InitTermios() {
46 // Some sane values that produce good result. 49 // Some sane values that produce good result.
47 termios_.c_iflag = ICRNL | IXON | IXOFF | IUTF8; 50 termios_.c_iflag = ICRNL | IXON | IXOFF | IUTF8;
48 termios_.c_oflag = OPOST | ONLCR; 51 termios_.c_oflag = OPOST | ONLCR;
49 termios_.c_cflag = CREAD | 077; 52 termios_.c_cflag = CREAD | 077;
50 termios_.c_lflag = 53 termios_.c_lflag =
51 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN; 54 ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHOCTL | ECHOKE | IEXTEN;
52 termios_.c_ispeed = B38400; 55 termios_.c_ispeed = B38400;
(...skipping 10 matching lines...) Expand all
63 termios_.c_cc[VSTOP] = 19; 66 termios_.c_cc[VSTOP] = 19;
64 termios_.c_cc[VSUSP] = 26; 67 termios_.c_cc[VSUSP] = 26;
65 termios_.c_cc[VEOL] = 0; 68 termios_.c_cc[VEOL] = 0;
66 termios_.c_cc[VREPRINT] = 18; 69 termios_.c_cc[VREPRINT] = 18;
67 termios_.c_cc[VDISCARD] = 15; 70 termios_.c_cc[VDISCARD] = 15;
68 termios_.c_cc[VWERASE] = 23; 71 termios_.c_cc[VWERASE] = 23;
69 termios_.c_cc[VLNEXT] = 22; 72 termios_.c_cc[VLNEXT] = 22;
70 termios_.c_cc[VEOL2] = 0; 73 termios_.c_cc[VEOL2] = 0;
71 } 74 }
72 75
73 MountNodeTty::~MountNodeTty() { 76 EventEmitter* MountNodeTty::GetEventEmitter() {
74 pthread_cond_destroy(&is_readable_cond_); 77 return emitter_.get();
75 } 78 }
76 79
77 Error MountNodeTty::Write(size_t offs, 80 Error MountNodeTty::Write(size_t offs,
78 const void* buf, 81 const void* buf,
79 size_t count, 82 size_t count,
80 int* out_bytes) { 83 int* out_bytes) {
84
81 AUTO_LOCK(output_lock_); 85 AUTO_LOCK(output_lock_);
82 *out_bytes = 0; 86 *out_bytes = 0;
83 87
84 // No handler registered. 88 // No handler registered.
85 if (output_handler_.handler == NULL) 89 if (output_handler_.handler == NULL)
86 return EIO; 90 return EIO;
87 91
88 int rtn = output_handler_.handler(static_cast<const char*>(buf), 92 int rtn = output_handler_.handler(static_cast<const char*>(buf),
89 count, 93 count,
90 output_handler_.user_data); 94 output_handler_.user_data);
91 95
92 // Negative return value means an error occured and the return 96 // Negative return value means an error occured and the return
93 // value is a negated errno value. 97 // value is a negated errno value.
94 if (rtn < 0) 98 if (rtn < 0)
95 return -rtn; 99 return -rtn;
96 100
97 *out_bytes = rtn; 101 *out_bytes = rtn;
98 return 0; 102 return 0;
99 } 103 }
100 104
105
101 Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) { 106 Error MountNodeTty::Read(size_t offs, void* buf, size_t count, int* out_bytes) {
102 AUTO_LOCK(node_lock_); 107 EventListenerLock wait(GetEventEmitter());
103 did_resize_ = false; 108 *out_bytes = 0;
104 while (!is_readable_) { 109
105 pthread_cond_wait(&is_readable_cond_, node_lock_.mutex()); 110 // If interrupted, return
106 if (!is_readable_ && did_resize_) { 111 Error err = wait.WaitOnEvent(POLLIN, -1);
107 // If an async resize event occured then return the failure and 112 if (err != 0)
108 // set EINTR. 113 return err;
109 *out_bytes = 0;
110 return EINTR;
111 }
112 }
113 114
114 size_t bytes_to_copy = std::min(count, input_buffer_.size()); 115 size_t bytes_to_copy = std::min(count, input_buffer_.size());
115
116 if (IS_ICANON) { 116 if (IS_ICANON) {
117 // Only read up to (and including) the first newline 117 // Only read up to (and including) the first newline
118 std::deque<char>::iterator nl = std::find(input_buffer_.begin(), 118 std::deque<char>::iterator nl = std::find(input_buffer_.begin(),
119 input_buffer_.end(), 119 input_buffer_.end(),
120 '\n'); 120 '\n');
121 121
122 if (nl != input_buffer_.end()) { 122 if (nl != input_buffer_.end()) {
123 // We found a newline in the buffer, adjust bytes_to_copy accordingly 123 // We found a newline in the buffer, adjust bytes_to_copy accordingly
124 size_t line_len = static_cast<size_t>(nl - input_buffer_.begin()) + 1; 124 size_t line_len = static_cast<size_t>(nl - input_buffer_.begin()) + 1;
125 bytes_to_copy = std::min(bytes_to_copy, line_len); 125 bytes_to_copy = std::min(bytes_to_copy, line_len);
126 } 126 }
127 } 127 }
128 128
129 129
130 // Copies data from the input buffer into buf. 130 // Copies data from the input buffer into buf.
131 std::copy(input_buffer_.begin(), input_buffer_.begin() + bytes_to_copy, 131 std::copy(input_buffer_.begin(), input_buffer_.begin() + bytes_to_copy,
132 static_cast<char*>(buf)); 132 static_cast<char*>(buf));
133 *out_bytes = bytes_to_copy; 133 *out_bytes = bytes_to_copy;
134 input_buffer_.erase(input_buffer_.begin(), 134 input_buffer_.erase(input_buffer_.begin(),
135 input_buffer_.begin() + bytes_to_copy); 135 input_buffer_.begin() + bytes_to_copy);
136 136
137 // mark input as no longer readable if we consumed 137 // mark input as no longer readable if we consumed
138 // the entire buffer or, in the case of buffered input, 138 // the entire buffer or, in the case of buffered input,
139 // we consumed the final \n char. 139 // we consumed the final \n char.
140 bool avail;
140 if (IS_ICANON) 141 if (IS_ICANON)
141 is_readable_ = 142 avail = std::find(input_buffer_.begin(),
142 std::find(input_buffer_.begin(), 143 input_buffer_.end(), '\n') != input_buffer_.end();
143 input_buffer_.end(), '\n') != input_buffer_.end();
144 else 144 else
145 is_readable_ = input_buffer_.size() > 0; 145 avail = input_buffer_.size() > 0;
146
147 if (!avail)
148 emitter_->ClearEvents_Locked(POLLIN);
146 149
147 return 0; 150 return 0;
148 } 151 }
149 152
150 Error MountNodeTty::Echo(const char* string, int count) { 153 Error MountNodeTty::Echo(const char* string, int count) {
151 int wrote; 154 int wrote;
152 Error error = Write(0, string, count, &wrote); 155 Error error = Write(0, string, count, &wrote);
153 if (error != 0 || wrote != count) { 156 if (error != 0 || wrote != count) {
154 // TOOD(sbc): Do something more useful in response to a 157 // TOOD(sbc): Do something more useful in response to a
155 // failure to echo. 158 // failure to echo.
156 return error; 159 return error;
157 } 160 }
158 161
159 return 0; 162 return 0;
160 } 163 }
161 164
162 Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) { 165 Error MountNodeTty::ProcessInput(struct tioc_nacl_input_string* message) {
163 AUTO_LOCK(node_lock_); 166 AUTO_LOCK(emitter_->GetLock())
164 167
165 const char* buffer = message->buffer; 168 const char* buffer = message->buffer;
166 size_t num_bytes = message->length; 169 size_t num_bytes = message->length;
167 170
168 for (size_t i = 0; i < num_bytes; i++) { 171 for (size_t i = 0; i < num_bytes; i++) {
169 char c = buffer[i]; 172 char c = buffer[i];
170 // Transform characters according to input flags. 173 // Transform characters according to input flags.
171 if (c == '\r') { 174 if (c == '\r') {
172 if (termios_.c_iflag & IGNCR) 175 if (termios_.c_iflag & IGNCR)
173 continue; 176 continue;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 } else { 216 } else {
214 Echo(&c, 1); 217 Echo(&c, 1);
215 } 218 }
216 } 219 }
217 } 220 }
218 221
219 if (!skip) 222 if (!skip)
220 input_buffer_.push_back(c); 223 input_buffer_.push_back(c);
221 224
222 if (c == '\n' || c == termios_.c_cc[VEOF] || !IS_ICANON) 225 if (c == '\n' || c == termios_.c_cc[VEOF] || !IS_ICANON)
223 is_readable_ = true; 226 emitter_->RaiseEvents_Locked(POLLIN);
224 }
225
226 if (is_readable_) {
227 RaiseEvent(POLLIN);
228 pthread_cond_broadcast(&is_readable_cond_);
229 } 227 }
230 228
231 return 0; 229 return 0;
232 } 230 }
233 231
234 Error MountNodeTty::Ioctl(int request, char* arg) { 232 Error MountNodeTty::Ioctl(int request, char* arg) {
235 switch (request) { 233 switch (request) {
236 case TIOCNACLOUTPUT: { 234 case TIOCNACLOUTPUT: {
237 AUTO_LOCK(output_lock_); 235 AUTO_LOCK(output_lock_);
238 if (arg == NULL) { 236 if (arg == NULL) {
(...skipping 14 matching lines...) Expand all
253 } 251 }
254 case TIOCSWINSZ: { 252 case TIOCSWINSZ: {
255 struct winsize* size = reinterpret_cast<struct winsize*>(arg); 253 struct winsize* size = reinterpret_cast<struct winsize*>(arg);
256 { 254 {
257 AUTO_LOCK(node_lock_); 255 AUTO_LOCK(node_lock_);
258 rows_ = size->ws_row; 256 rows_ = size->ws_row;
259 cols_ = size->ws_col; 257 cols_ = size->ws_col;
260 } 258 }
261 kill(getpid(), SIGWINCH); 259 kill(getpid(), SIGWINCH);
262 260
263 // Wake up any thread waiting on Read
264 { 261 {
265 AUTO_LOCK(node_lock_); 262 // Wake up any thread waiting on Read with EINTR
266 did_resize_ = true; 263 AUTO_LOCK(emitter_->GetLock())
267 pthread_cond_broadcast(&is_readable_cond_); 264 emitter_->RaiseEvents_Locked(POLLERR);
268 } 265 }
269 return 0; 266 return 0;
270 } 267 }
271 case TIOCGWINSZ: { 268 case TIOCGWINSZ: {
272 struct winsize* size = reinterpret_cast<struct winsize*>(arg); 269 struct winsize* size = reinterpret_cast<struct winsize*>(arg);
273 size->ws_row = rows_; 270 size->ws_row = rows_;
274 size->ws_col = cols_; 271 size->ws_col = cols_;
275 return 0; 272 return 0;
276 } 273 }
277 } 274 }
278 275
279 return EINVAL; 276 return EINVAL;
280 } 277 }
281 278
282 Error MountNodeTty::Tcgetattr(struct termios* termios_p) { 279 Error MountNodeTty::Tcgetattr(struct termios* termios_p) {
283 AUTO_LOCK(node_lock_); 280 AUTO_LOCK(node_lock_);
284 *termios_p = termios_; 281 *termios_p = termios_;
285 return 0; 282 return 0;
286 } 283 }
287 284
288 Error MountNodeTty::Tcsetattr(int optional_actions, 285 Error MountNodeTty::Tcsetattr(int optional_actions,
289 const struct termios *termios_p) { 286 const struct termios *termios_p) {
290 AUTO_LOCK(node_lock_); 287 AUTO_LOCK(node_lock_);
291 termios_ = *termios_p; 288 termios_ = *termios_p;
292 return 0; 289 return 0;
293 } 290 }
294 291
295 } 292 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698