[pulseaudio-discuss] [PATCH]raop2: Blocking UDP sockets (was: An raop2 support)

Matthias Wabersich pulseaudio at niafc.de
Thu Sep 12 12:40:32 PDT 2013


Hi Anton,

> I also se some: D:  [lt-pulseaudio] rtsp_client.c: Sending command:
> RECORD E: [raop-sink] module-raop-sink.c: Failed to send UDP packet:
> Resource temporarily unavailable

I wrote a short patch for this case (see [1]) against Hajime's
raop2-for-merge branch.
I found my suspected reason (at least in my case) to hold true. Just
after connection to the UDP streaming port of my remote device was
established, I encountered the same issue you described above.
Using a debugger one could see that the number of bytes written by
pa_write() in udp_send_audio_packet() was higher than the UDP send
buffer of my host (as seen in /proc/sys/net/core/wmem_max), which leads
to pa_write() returning -1 and setting errno to 11 (EAGAIN).

As the manpage of send(2) states, one should use select(2) to determine
when the send buffer is free again. I implemented this using pa_poll()
in raop_client.c.

It would be great if you could give it a try.

Greetings,

Matthias

[1]: Patch to raop_client.c to support EAGAIN with non-blocking UDP socket
diff --git a/src/modules/raop/raop_client.c b/src/modules/raop/raop_client.c
index d320ea5..27b29e7 100644
--- a/src/modules/raop/raop_client.c
+++ b/src/modules/raop/raop_client.c
@@ -54,6 +54,7 @@
  #include <pulsecore/macro.h>
  #include <pulsecore/memchunk.h>
  #include <pulsecore/random.h>
+#include <pulsecore/poll.h>

  #include "raop_client.h"
  #include "rtsp_client.h"
@@ -558,9 +559,21 @@ static void udp_build_retrans_header(uint32_t
*buffer, size_t size, uint16_t seq
  static ssize_t udp_send_audio_packet(pa_raop_client *c, pa_bool_t
retrans, uint8_t *buffer, size_t size) {
      ssize_t length;
      int fd = retrans ? c->udp_control_fd : c->udp_stream_fd;
+    struct pollfd block_fd;

-    length = pa_write(fd, buffer, size, NULL);
+    for(;;) {
+        length = pa_write(fd, buffer, size, NULL);

+        if ((length < 0) && ((errno == EAGAIN) || (errno ==
EWOULDBLOCK))  ) {
+            pa_log_debug("Non-blocking socket blocked, retrying packet
%d", c->seq);
+            block_fd.fd = fd;
+            block_fd.events = POLLOUT;
+            if (pa_poll(&block_fd, 1, -1) >= 0)
+                continue;
+        } else
+            break;
+
+    }
      return length;
  }



More information about the pulseaudio-discuss mailing list