multisocketsink: handle client close correctly and EWOULDBLOCK
authorTom Deseyn <tom.deseyn@gmail.com>
Thu, 28 Jan 2016 15:26:47 +0000 (16:26 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Tue, 1 Mar 2016 13:15:38 +0000 (13:15 +0000)
Fixes 100% cpu usage when client disconnects. Commit 6db2ee56
would just make multisocketsink ignore reads of 0 bytes without
removing the client, so we'd get woken up over and over again
for the client.

Fix the original issue differently by handling the non-fatal error code.

https://bugzilla.gnome.org/show_bug.cgi?id=761257
https://bugzilla.gnome.org/show_bug.cgi?id=743834

gst/tcp/gstmultisocketsink.c

index f9acc13..2f1a9ae 100644 (file)
@@ -616,11 +616,11 @@ gst_multi_socket_sink_handle_client_read (GstMultiSocketSink * sink,
   ret = TRUE;
 
   navail = g_socket_get_available_bytes (mhclient->handle.socket);
-  if (navail <= 0)
+  if (navail < 0)
     return TRUE;
 
   /* only collect the data in a buffer when we need to send it with an event */
-  do_event = sink->send_messages;
+  do_event = sink->send_messages && navail > 0;
   if (do_event) {
     omem = mem = g_malloc (navail);
     maxmem = navail;
@@ -632,7 +632,7 @@ gst_multi_socket_sink_handle_client_read (GstMultiSocketSink * sink,
   /* just Read 'n' Drop, could also just drop the client as it's not supposed
    * to write to us except for closing the socket, I guess it's because we
    * like to listen to our customers. */
-  while (navail > 0) {
+  do {
     GST_DEBUG_OBJECT (sink, "%s client wants us to read", mhclient->debug);
 
     nread =
@@ -647,6 +647,9 @@ gst_multi_socket_sink_handle_client_read (GstMultiSocketSink * sink,
       ret = FALSE;
       break;
     } else if (nread < 0) {
+      if (err->code == G_IO_ERROR_WOULD_BLOCK)
+        break;
+
       GST_WARNING_OBJECT (sink, "%s could not read: %s",
           mhclient->debug, err->message);
       mhclient->status = GST_CLIENT_STATUS_ERROR;
@@ -657,7 +660,7 @@ gst_multi_socket_sink_handle_client_read (GstMultiSocketSink * sink,
     if (do_event)
       mem += nread;
     first = FALSE;
-  }
+  } while (navail > 0);
   g_clear_error (&err);
 
   if (do_event) {