aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2017-06-02 15:02:56 +0200
committerMatthias P. Braendli <matthias.braendli@mpb.li>2017-06-02 15:02:56 +0200
commit7610a41afe910df6426aa09eae5aad7431d69e36 (patch)
tree1b86d67a4230819a5f4ee8ef1e92e2ee70d57f09
parent8bd4a04c4098e1dfe75f8056d4ff5a125d445275 (diff)
downloaddabmux-7610a41afe910df6426aa09eae5aad7431d69e36.tar.gz
dabmux-7610a41afe910df6426aa09eae5aad7431d69e36.tar.bz2
dabmux-7610a41afe910df6426aa09eae5aad7431d69e36.zip
TCP output: do not block in the destructor if one connection stalls
-rw-r--r--src/TcpSocket.cpp22
-rw-r--r--src/TcpSocket.h5
-rw-r--r--src/dabOutput/dabOutputTcp.cpp12
3 files changed, 34 insertions, 5 deletions
diff --git a/src/TcpSocket.cpp b/src/TcpSocket.cpp
index b9824fa..40c1c1a 100644
--- a/src/TcpSocket.cpp
+++ b/src/TcpSocket.cpp
@@ -2,7 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in
Right of Canada (Communications Research Center Canada)
- Copyright (C) 2016
+ Copyright (C) 2017
Matthias P. Braendli, matthias.braendli@mpb.li
http://www.opendigitalradio.org
@@ -132,8 +132,26 @@ ssize_t TcpSocket::recv(void* data, size_t size)
}
-ssize_t TcpSocket::send(const void* data, size_t size)
+ssize_t TcpSocket::send(const void* data, size_t size, int timeout_ms)
{
+ if (timeout_ms) {
+ struct pollfd fds[1];
+ fds[0].fd = m_sock;
+ fds[0].events = POLLOUT;
+
+ int retval = poll(fds, 1, timeout_ms);
+
+ if (retval == -1) {
+ stringstream ss;
+ ss << "TCP Socket send error on poll(): " << strerror(errno);
+ throw std::runtime_error(ss.str());
+ }
+ else if (retval == 0) {
+ // Timed out
+ return 0;
+ }
+ }
+
/* Without MSG_NOSIGNAL the process would receive a SIGPIPE and die */
ssize_t ret = ::send(m_sock, (const char*)data, size, MSG_NOSIGNAL);
diff --git a/src/TcpSocket.h b/src/TcpSocket.h
index 660515d..9ff09e5 100644
--- a/src/TcpSocket.h
+++ b/src/TcpSocket.h
@@ -2,7 +2,7 @@
Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Her Majesty the Queen in
Right of Canada (Communications Research Center Canada)
- Copyright (C) 2016
+ Copyright (C) 2017
Matthias P. Braendli, matthias.braendli@mpb.li
http://www.opendigitalradio.org
@@ -77,9 +77,10 @@ class TcpSocket
/** Send data over the TCP connection.
* @param data The buffer that will be sent.
* @param size Number of bytes to send.
+ * @param timeout_ms number of milliseconds before timeout
* return number of bytes sent or -1 if error
*/
- ssize_t send(const void* data, size_t size);
+ ssize_t send(const void* data, size_t size, int timeout_ms=0);
/** Receive data from the socket.
* @param data The buffer that will receive data.
diff --git a/src/dabOutput/dabOutputTcp.cpp b/src/dabOutput/dabOutputTcp.cpp
index 2aab48a..f5aebe0 100644
--- a/src/dabOutput/dabOutputTcp.cpp
+++ b/src/dabOutput/dabOutputTcp.cpp
@@ -89,7 +89,17 @@ class TCPConnection
queue.wait_and_pop(data);
try {
- m_sock.send(&data[0], data.size());
+ ssize_t sent = 0;
+ do {
+ const int timeout_ms = 10; // Less than one ETI frame
+ sent = m_sock.send(&data[0], data.size(), timeout_ms);
+
+ if (is_overloaded()) {
+ m_running = false;
+ break;
+ }
+ }
+ while (sent == 0);
}
catch (std::runtime_error& e) {
m_running = false;