RE: Is this a bug of GMainLoop?



Thanks for your reply.
Yes, it works in linux.

The following is the log by setting G_IO_WIN32_DEBUG:
1 g_io_channel_win32_new_socket: sockfd=1880
2 g_io_win32_sock_set_flags: NONBLOCK
3 g_io_win32_sock_create_watch: sock=1880 handle=0x73c condition={IN|OUT|ERR}
4 g_io_win32_prepare: WSAEventSelect(1880, 0x73c, {READ|WRITE|ACCEPT|CONNECT|CLOSE}
5 g_io_win32_check: WSAEnumNetworkEvents (1880, 0x73c) revents={IN|OUT} condition={IN|OUT|ERR} events={WRITE|CONNECT}
6 g_io_win32_dispatch: pollfd.revents=OUT condition=IN|OUT|ERR result=OUT
First send_cb write char, status: 1.
7 g_io_win32_sock_create_watch: sock=1880 handle=0x73c condition={IN|ERR}
8 g_io_win32_finalize: channel is for sock=1880
9 g_io_win32_prepare: WSAEventSelect(1880, 0x73c, {READ|ACCEPT|CLOSE}
10 g_io_win32_check: WSAEnumNetworkEvents (1880, 0x73c) revents={IN} condition={IN|ERR} events={}
11 g_io_win32_check: WSAEventSelect(1880, 0x73c, {})
12 g_io_win32_check: ResetEvent(0x73c)
13 g_io_win32_prepare: WSAEventSelect(1880, 0x73c, {READ|ACCEPT|CLOSE}
14 g_io_win32_finalize: channel is for sock=1880
15 g_io_win32_sock_create_watch: sock=1880 handle=0x73c condition={IN|OUT|ERR}
16 g_io_win32_prepare: WSAEventSelect(1880, 0x73c, {READ|WRITE|ACCEPT|CONNECT|CLOSE}

I think the problem is: line 5 shows the g_poll returns FD_WRITE, and according to
	  if (watch->pollfd.revents != 0 &&
	      events.lNetworkEvents == 0 &&
	      !(channel->event_mask & FD_WRITE))
	    {
			...
			ResetEvent ((HANDLE) watch->pollfd.fd);
			...
		}
The event will not be reset. Since it is not reset, the g_poll will signal this FD_WRITE event again. This is shown in line 10: revents={IN}, but events={}.
And in line 12, the event is reset. So the next g_poll will check FD_WRITE event of the socket. However, according to msdn documentation of WSAEventSelect,
----------------------------
The FD_WRITE network event is handled slightly differently. An FD_WRITE network event is recorded when a socket is first connected with connect/WSAConnect or accepted with accept/WSAAccept, and then after a send fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE network event setting and lasting until a send returns WSAEWOULDBLOCK. After such a failure the application will find out that sends are again possible when an FD_WRITE network event is recorded and the associated event object is set.
----------------------------
The FD_WRITE event of the socket will not be signaled. As a result, g_poll will block and not return.

I add the following in line giowin32.c:841, the program can work.
          channel->event_mask = event_mask;
#if 0
          channel->event = watch->pollfd.fd;
#endif
          channel->last_events = 1;
+        if (event_mask & FD_WRITE && !channel->write_would_have_blocked)
+          WSASetEvent (watch->pollfd.fd);
        }
      break;
But I don't know whether it affects other part of glib program.

Regards,
YuKuan

-----Original Message-----
From: tlillqvist gmail com [mailto:tlillqvist gmail com] On Behalf Of Tor Lillqvist
Sent: 星期四, 15 五月, 2008 AM 1:53
To: #YU KUAN#
Cc: gtk-devel-list gnome org
Subject: Re: Is this a bug of GMainLoop?

Have you, by the way, verified that the corresponding program works on Linux?

--tml


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