[glib] gsocket: add a testcase that shows a hang on win32



commit 4f4714285dcc5c3ce9c87f65d9f684f285113a6e
Author: Paolo Borelli <pborelli gnome org>
Date:   Sat Jan 10 15:23:07 2015 +0100

    gsocket: add a testcase that shows a hang on win32
    
    Add a unit test that checks g_socket_new_from_fd by creating
    a gsocket, obtaining its fd, duplicating the fd and then creating
    a gsocket from the new fd. This shows a hang on win32 since the
    gsocket created from the fd never receives the FD_WRITE event
    because we wait for the condition without first trying to write
    and windows signals the condition only after a EWOULDBLOCK error.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=741707

 gio/tests/socket.c |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 94 insertions(+), 0 deletions(-)
---
diff --git a/gio/tests/socket.c b/gio/tests/socket.c
index 4c3f69b..a1f48bc 100644
--- a/gio/tests/socket.c
+++ b/gio/tests/socket.c
@@ -929,6 +929,99 @@ test_timed_wait (void)
   g_slice_free (IPTestData, data);
 }
 
+static int
+duplicate_fd(int fd)
+{
+#ifdef G_OS_WIN32
+    HANDLE newfd;
+
+    if (!DuplicateHandle (GetCurrentProcess (),
+                          (HANDLE)fd,
+                          GetCurrentProcess (),
+                          &newfd,
+                          0,
+                          FALSE,
+                           DUPLICATE_SAME_ACCESS))
+    {
+        return -1;
+    }
+
+    return (int)newfd;
+#else
+    return dup(fd);
+#endif
+}
+
+static void
+test_fd_roundtrip (void)
+{
+  IPTestData *data;
+  GError *error = NULL;
+  GSocket *client;
+  GSocket *client2;
+  GSocketAddress *addr;
+  int fd;
+  gssize len;
+  gchar buf[128];
+
+  data = create_server (G_SOCKET_FAMILY_IPV4, echo_server_thread, FALSE);
+  addr = g_socket_get_local_address (data->server, &error);
+  g_assert_no_error (error);
+
+  client = g_socket_new (G_SOCKET_FAMILY_IPV4,
+                         G_SOCKET_TYPE_STREAM,
+                         G_SOCKET_PROTOCOL_DEFAULT,
+                         &error);
+  g_assert_no_error (error);
+
+  g_socket_set_blocking (client, TRUE);
+  g_socket_set_timeout (client, 1);
+
+  g_socket_connect (client, addr, NULL, &error);
+  g_assert_no_error (error);
+  g_assert (g_socket_is_connected (client));
+  g_object_unref (addr);
+
+  /* we have to dup otherwise the fd gets closed twice on unref */
+  fd = duplicate_fd (g_socket_get_fd (client));
+  client2 = g_socket_new_from_fd (fd, &error);
+  g_assert_no_error (error);
+
+  g_assert_cmpint (g_socket_get_family (client2), ==, g_socket_get_family (client));
+  g_assert_cmpint (g_socket_get_socket_type (client2), ==, g_socket_get_socket_type (client));
+  g_assert_cmpint (g_socket_get_protocol (client2), ==, G_SOCKET_PROTOCOL_TCP);
+
+  len = g_socket_send (client2, testbuf, strlen (testbuf) + 1, NULL, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (len, ==, strlen (testbuf) + 1);
+
+  len = g_socket_receive (client2, buf, sizeof (buf), NULL, &error);
+  g_assert_no_error (error);
+  g_assert_cmpint (len, ==, strlen (testbuf) + 1);
+
+  g_assert_cmpstr (testbuf, ==, buf);
+
+  g_socket_shutdown (client, FALSE, TRUE, &error);
+  g_assert_no_error (error);
+  g_socket_shutdown (client2, FALSE, TRUE, &error);
+  g_assert_no_error (error);
+
+  g_thread_join (data->thread);
+
+  g_socket_close (client, &error);
+  g_assert_no_error (error);
+  g_socket_close (client2, &error);
+  g_assert_no_error (error);
+  g_socket_close (data->server, &error);
+  g_assert_no_error (error);
+
+  g_object_unref (data->server);
+  g_object_unref (client);
+  g_object_unref (client2);
+
+  g_slice_free (IPTestData, data);
+}
+
 static void
 test_sockaddr (void)
 {
@@ -1355,6 +1448,7 @@ main (int   argc,
 #endif
   g_test_add_func ("/socket/close_graceful", test_close_graceful);
   g_test_add_func ("/socket/timed_wait", test_timed_wait);
+  g_test_add_func ("/socket/fd_roundtrip", test_fd_roundtrip);
   g_test_add_func ("/socket/address", test_sockaddr);
 #ifdef G_OS_UNIX
   g_test_add_func ("/socket/unix-from-fd", test_unix_from_fd);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]