From 49ae05877072aeaa500546415bf950416b20694e Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 23 Jan 2012 14:28:16 -0600 Subject: [PATCH] Found an error in my buffering code and added a timeout to write --- src/impl/unix.cc | 54 ++++++++++++++++++++++++++++++++++++------------ src/serial.cc | 4 ++-- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/impl/unix.cc b/src/impl/unix.cc index 24ad257..207eaf0 100644 --- a/src/impl/unix.cc +++ b/src/impl/unix.cc @@ -265,7 +265,6 @@ Serial::SerialImpl::read (char* buf, size_t size) bytes_read = ::read (fd_, buf, size); // read should always return some data as select reported it was // ready to read when we get to this point. - // printf("bytes_read: %lu\n", bytes_read); if (bytes_read < 1) { // Disconnected devices, at least on Linux, show the @@ -291,25 +290,54 @@ Serial::SerialImpl::write (const string &data) { throw PortNotOpenedException ("Serial::write"); } - - ssize_t n = ::write (fd_, data.c_str (), data.length ()); - - if (n != static_cast (data.length ())) + + fd_set writefds; + ssize_t bytes_written = 0; + while (true) { - throw IOException ("Write did not complete"); - } - else if (n == -1) - { - if (errno == EINTR) + if (timeout_ != -1) { - return write (data); + FD_ZERO (&writefds); + FD_SET (fd_, &writefds); + struct timeval timeout; + timeout.tv_sec = timeout_ / 1000; + timeout.tv_usec = static_cast (timeout_ % 1000) * 1000; + int r = select (fd_ + 1, NULL, &writefds, NULL, &timeout); + + if (r == -1 && errno == EINTR) + continue; + + if (r == -1) + { + throw IOException (errno); + } + } + + if (timeout_ == -1 || FD_ISSET (fd_, &writefds)) + { + bytes_written = ::write (fd_, data.c_str (), data.length ()); + // read should always return some data as select reported it was + // ready to read when we get to this point. + if (bytes_written < 1) + { + // Disconnected devices, at least on Linux, show the + // behavior that they are always ready to read immediately + // but reading returns nothing. + throw SerialExecption ("device reports readiness to read but " + "returned no data (device disconnected?)"); + } + break; } else { - throw IOException (errno); + break; } } - return static_cast (n); + if (bytes_written != static_cast (data.length ())) + { + throw IOException ("Write did not complete"); + } + return static_cast (bytes_written); } void diff --git a/src/serial.cc b/src/serial.cc index c8ac752..6e79459 100644 --- a/src/serial.cc +++ b/src/serial.cc @@ -91,7 +91,7 @@ Serial::read (size_t size) } else { - // Needs to read, loop until we have read enough... or timeout + // Needs to read, loop until we have read enough or timeout size_t chars_left = 0; string result = ""; @@ -114,8 +114,8 @@ Serial::read (size_t size) *(read_cache_ + chars_read) = '\0'; if (chars_left > chars_read) { + result.append (read_cache_, chars_read); memset (read_cache_, 0, buffer_size_); - result.append (read_cache_); chars_left -= chars_read; } else