From 58a123c907b38ebf87ae1993e1e8572c21d32f91 Mon Sep 17 00:00:00 2001
From: Josh Blum <josh@joshknows.com>
Date: Mon, 14 Jan 2013 13:58:42 -0800
Subject: udp: fix ENOBUFS with send/retry for udp socket

---
 host/lib/transport/udp_zero_copy.cpp | 18 ++++++++++++++++--
 1 file changed, 16 insertions(+), 2 deletions(-)

(limited to 'host/lib')

diff --git a/host/lib/transport/udp_zero_copy.cpp b/host/lib/transport/udp_zero_copy.cpp
index 9125be53a..166177177 100644
--- a/host/lib/transport/udp_zero_copy.cpp
+++ b/host/lib/transport/udp_zero_copy.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright 2010-2012 Ettus Research LLC
+// Copyright 2010-2013 Ettus Research LLC
 //
 // This program is free software: you can redistribute it and/or modify
 // it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
 #include <uhd/utils/atomic.hpp>
 #include <boost/format.hpp>
 #include <boost/make_shared.hpp>
+#include <boost/thread/thread.hpp> //sleep
 #include <vector>
 
 using namespace uhd;
@@ -112,7 +113,20 @@ public:
         _mem(mem), _sock_fd(sock_fd), _frame_size(frame_size) { /*NOP*/ }
 
     void release(void){
-        UHD_ASSERT_THROW(::send(_sock_fd, (const char *)_mem, size(), 0) == ssize_t(size()));
+        //Retry logic because send may fail with ENOBUFS.
+        //This is known to occur at least on some OSX systems.
+        //But it should be safe to always check for the error.
+        while (true)
+        {
+            const ssize_t ret = ::send(_sock_fd, (const char *)_mem, size(), 0);
+            if (ret == ssize_t(size())) break;
+            if (ret == -1 and errno == ENOBUFS)
+            {
+                boost::this_thread::sleep(boost::posix_time::microseconds(1));
+                continue; //try to send again
+            }
+            UHD_ASSERT_THROW(ret == ssize_t(size()));
+        }
         _claimer.release();
     }
 
-- 
cgit v1.2.3