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

Side by Side Diff: device/serial/serial_io_handler_posix.cc

Issue 2057973002: [serial] When a read is requested on posix platforms, try the read immediately. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Prevent unexpected reentrancy Created 4 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 unified diff | Download patch
« no previous file with comments | « device/serial/serial_io_handler_posix.h ('k') | 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "device/serial/serial_io_handler_posix.h" 5 #include "device/serial/serial_io_handler_posix.h"
6 6
7 #include <sys/ioctl.h> 7 #include <sys/ioctl.h>
8 #include <termios.h> 8 #include <termios.h>
9 9
10 #include "base/posix/eintr_wrapper.h" 10 #include "base/posix/eintr_wrapper.h"
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 return new SerialIoHandlerPosix(file_thread_task_runner, 117 return new SerialIoHandlerPosix(file_thread_task_runner,
118 ui_thread_task_runner); 118 ui_thread_task_runner);
119 } 119 }
120 120
121 void SerialIoHandlerPosix::ReadImpl() { 121 void SerialIoHandlerPosix::ReadImpl() {
122 DCHECK(CalledOnValidThread()); 122 DCHECK(CalledOnValidThread());
123 DCHECK(pending_read_buffer()); 123 DCHECK(pending_read_buffer());
124 DCHECK(file().IsValid()); 124 DCHECK(file().IsValid());
125 125
126 EnsureWatchingReads(); 126 EnsureWatchingReads();
127
128 // Try to read immediately. This is needed because on some platforms
129 // (e.g., OSX) there may not be a notification from the message loop
130 // when the fd is ready to read immediately after it is opened. There
131 // is no danger of blocking because the fd is opened with async flag.
132 AttemptRead(true);
127 } 133 }
128 134
129 void SerialIoHandlerPosix::WriteImpl() { 135 void SerialIoHandlerPosix::WriteImpl() {
130 DCHECK(CalledOnValidThread()); 136 DCHECK(CalledOnValidThread());
131 DCHECK(pending_write_buffer()); 137 DCHECK(pending_write_buffer());
132 DCHECK(file().IsValid()); 138 DCHECK(file().IsValid());
133 139
134 EnsureWatchingWrites(); 140 EnsureWatchingWrites();
135 } 141 }
136 142
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 is_watching_writes_(false) { 293 is_watching_writes_(false) {
288 } 294 }
289 295
290 SerialIoHandlerPosix::~SerialIoHandlerPosix() { 296 SerialIoHandlerPosix::~SerialIoHandlerPosix() {
291 } 297 }
292 298
293 void SerialIoHandlerPosix::OnFileCanReadWithoutBlocking(int fd) { 299 void SerialIoHandlerPosix::OnFileCanReadWithoutBlocking(int fd) {
294 DCHECK(CalledOnValidThread()); 300 DCHECK(CalledOnValidThread());
295 DCHECK_EQ(fd, file().GetPlatformFile()); 301 DCHECK_EQ(fd, file().GetPlatformFile());
296 302
303 AttemptRead(false);
304 }
305
306 void SerialIoHandlerPosix::AttemptRead(bool within_read) {
297 if (pending_read_buffer()) { 307 if (pending_read_buffer()) {
298 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(), 308 int bytes_read = HANDLE_EINTR(read(file().GetPlatformFile(),
299 pending_read_buffer(), 309 pending_read_buffer(),
300 pending_read_buffer_len())); 310 pending_read_buffer_len()));
301 if (bytes_read < 0) { 311 if (bytes_read < 0) {
302 if (errno == ENXIO) { 312 if (errno == EAGAIN) {
303 ReadCompleted(0, serial::ReceiveError::DEVICE_LOST); 313 // The fd does not have data to read yet so continue waiting.
314 return;
315 } else if (errno == ENXIO) {
316 RunReadCompleted(within_read, 0, serial::ReceiveError::DEVICE_LOST);
304 } else { 317 } else {
305 ReadCompleted(0, serial::ReceiveError::SYSTEM_ERROR); 318 RunReadCompleted(within_read, 0, serial::ReceiveError::SYSTEM_ERROR);
306 } 319 }
307 } else if (bytes_read == 0) { 320 } else if (bytes_read == 0) {
308 ReadCompleted(0, serial::ReceiveError::DEVICE_LOST); 321 RunReadCompleted(within_read, 0, serial::ReceiveError::DEVICE_LOST);
309 } else { 322 } else {
310 bool break_detected = false; 323 bool break_detected = false;
311 bool parity_error_detected = false; 324 bool parity_error_detected = false;
312 int new_bytes_read = 325 int new_bytes_read =
313 CheckReceiveError(pending_read_buffer(), pending_read_buffer_len(), 326 CheckReceiveError(pending_read_buffer(), pending_read_buffer_len(),
314 bytes_read, break_detected, parity_error_detected); 327 bytes_read, break_detected, parity_error_detected);
315 328
316 if (break_detected) { 329 if (break_detected) {
317 ReadCompleted(new_bytes_read, serial::ReceiveError::BREAK); 330 RunReadCompleted(within_read, new_bytes_read,
331 serial::ReceiveError::BREAK);
318 } else if (parity_error_detected) { 332 } else if (parity_error_detected) {
319 ReadCompleted(new_bytes_read, serial::ReceiveError::PARITY_ERROR); 333 RunReadCompleted(within_read, new_bytes_read,
334 serial::ReceiveError::PARITY_ERROR);
320 } else { 335 } else {
321 ReadCompleted(new_bytes_read, serial::ReceiveError::NONE); 336 RunReadCompleted(within_read, new_bytes_read,
337 serial::ReceiveError::NONE);
322 } 338 }
323 } 339 }
324 } else { 340 } else {
325 // Stop watching the fd if we get notifications with no pending 341 // Stop watching the fd if we get notifications with no pending
326 // reads or writes to avoid starving the message loop. 342 // reads or writes to avoid starving the message loop.
327 is_watching_reads_ = false; 343 is_watching_reads_ = false;
328 file_read_watcher_.StopWatchingFileDescriptor(); 344 file_read_watcher_.StopWatchingFileDescriptor();
329 } 345 }
330 } 346 }
331 347
348 void SerialIoHandlerPosix::RunReadCompleted(bool within_read,
349 int bytes_read,
350 serial::ReceiveError error) {
351 if (within_read) {
352 // Stop watching the fd because a read completed within the read call.
Reilly Grant (use Gerrit) 2016/07/27 21:23:38 This isn't necessary. The code is optimized to ass
aschulman 2016/07/28 03:11:00 I think I may be confused. In your prior comment y
353 is_watching_reads_ = false;
354 file_read_watcher_.StopWatchingFileDescriptor();
355
356 QueueReadCompleted(bytes_read, error);
357 } else {
358 ReadCompleted(bytes_read, error);
359 }
360 }
361
332 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking(int fd) { 362 void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking(int fd) {
333 DCHECK(CalledOnValidThread()); 363 DCHECK(CalledOnValidThread());
334 DCHECK_EQ(fd, file().GetPlatformFile()); 364 DCHECK_EQ(fd, file().GetPlatformFile());
335 365
336 if (pending_write_buffer()) { 366 if (pending_write_buffer()) {
337 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(), 367 int bytes_written = HANDLE_EINTR(write(file().GetPlatformFile(),
338 pending_write_buffer(), 368 pending_write_buffer(),
339 pending_write_buffer_len())); 369 pending_write_buffer_len()));
340 if (bytes_written < 0) { 370 if (bytes_written < 0) {
341 WriteCompleted(0, serial::SendError::SYSTEM_ERROR); 371 WriteCompleted(0, serial::SendError::SYSTEM_ERROR);
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after
612 memcpy(buffer, chars_stashed_, std::min(new_bytes_read, 2)); 642 memcpy(buffer, chars_stashed_, std::min(new_bytes_read, 2));
613 memcpy(chars_stashed_, tmp, num_chars_stashed_); 643 memcpy(chars_stashed_, tmp, num_chars_stashed_);
614 return new_bytes_read; 644 return new_bytes_read;
615 } 645 }
616 646
617 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) { 647 std::string SerialIoHandler::MaybeFixUpPortName(const std::string& port_name) {
618 return port_name; 648 return port_name;
619 } 649 }
620 650
621 } // namespace device 651 } // namespace device
OLDNEW
« no previous file with comments | « device/serial/serial_io_handler_posix.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698