Is this a bug of GMainLoop?



I write a client network program using GIOChannel and GMainLoop on windows.

The server program is a simple sink server, which eats all input.

The client program first connects server, then watches for G_IO_IN and G_IO_OUT

and creates a thread which do g_main_loop_run.

Surely G_IO_OUT is ok, the mainloop thread returns from poll and sends one byte to server in callback.

Then watches for G_IO_IN. mainloop thread will block.

Then sleep for a while, watches for G_IO_OUT.

I wish the mainloop thread to return from poll with G_IO_OUT event.

However, now mainloop will block instead of returning from poll.

 

I think the problem is FD_WRITE will not signaled again until send returns WSAEWOULDBLOCK on windows.

Is this a bug of GMainLoop?

Thanks.

 

The client program source code:

-----------------------------------------------------------------------

#include <winsock2.h>

 

#include "glib.h"

 

 

guint source_id;

GMutex *mutex;

GCond *cond;

 

 

gboolean

recv_cb (GIOChannel *source,

         GIOCondition condition,

         gpointer data)

{

  g_assert_not_reached ();

}

 

gboolean

send_cb (GIOChannel *source,

         GIOCondition condition,

         gpointer data)

{

  gboolean is_second = (gboolean) data;

  GIOStatus status;

  gsize bytes_written;

  gchar c = 'T';

 

  status = g_io_channel_write_chars (source, &c, 1, &bytes_written, NULL);

  g_print ("%s send_cb write char, status: %d.\n",

           (is_second ? "Second" : "First"),

           status);

 

  g_source_remove (source_id);

 

  source_id = g_io_add_watch (source,

                               G_IO_IN | G_IO_ERR,

                               recv_cb,

                               NULL);

 

  g_mutex_lock (mutex);

  g_cond_signal (cond);

  g_mutex_unlock (mutex);

 

  return (TRUE);

}

 

int

main (int argc, char **argv)

{

  WSADATA wsa_data;

  SOCKET s;

  struct sockaddr_in addr;

  gint addrlen = sizeof (addr);

 

  GIOChannel *channel;

  GMainLoop *loop;

  GThread *thread;

 

  g_assert (WSAStartup(0x0202, &wsa_data) == 0);

  g_thread_init (NULL);

 

  mutex = g_mutex_new ();

  cond = g_cond_new ();

 

  s = socket (AF_INET, SOCK_STREAM, 0);

  g_assert (s != INVALID_SOCKET);

 

  g_assert (WSAStringToAddress ("155.69.149.175:5555",

                                  AF_INET,

                                  NULL,

                                  (PSOCKADDR)&addr,

                                  &addrlen)

            != SOCKET_ERROR);

 

  g_assert (connect (s, (struct sockaddr *) &addr, sizeof (addr)) != SOCKET_ERROR);

 

  channel = g_io_channel_win32_new_socket (s);

 

  loop = g_main_loop_new (NULL, FALSE);

  g_assert (loop);

 

  thread = g_thread_create ((GThreadFunc) g_main_loop_run,

                             loop,

                             TRUE,

                             NULL);

  g_assert (thread);

 

 

  g_mutex_lock (mutex);

  source_id = g_io_add_watch (channel,

                               G_IO_IN | G_IO_ERR | G_IO_OUT,

                               send_cb,

                               (gpointer) FALSE);

  g_cond_wait (cond, mutex);

  g_mutex_unlock (mutex);

 

  g_usleep (500000);

 

  g_source_remove (source_id);

 

  g_usleep (500000);

 

  g_mutex_lock (mutex);

  source_id = g_io_add_watch (channel,

                               G_IO_IN | G_IO_ERR | G_IO_OUT,

                               send_cb,

                               (gpointer) TRUE);

  g_cond_wait (cond, mutex);

  g_mutex_unlock (mutex);

 

  g_main_loop_quit (loop);

  g_thread_join (thread);

 

  return (0);

}



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