|
View:
New views
8 Messages
—
Rating Filter:
Alert me
|
|
|
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. At this point G_IO_OUT is surely
ok, the mainloop thread returns from poll and sends one byte to server in
callback. Then the program watches
for G_IO_IN. mainloop thread will block. Then the program sleeps
for a while, and watches for G_IO_OUT. Here, I wish the mainloop
thread to return from poll with G_IO_OUT event. However, 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); } _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
Re: Is this a bug of GMainLoop?Hi,
Am Mittwoch, den 14.05.2008, 09:34 +0800 schrieb #YU KUAN#: > At this point G_IO_OUT is surely ok, the mainloop thread returns from > poll and sends one byte to server in callback. > > Then the program watches for G_IO_IN. mainloop thread will block. > > Then the program sleeps for a while, and watches for G_IO_OUT. > > Here, I wish the mainloop thread to return from poll with G_IO_OUT > event. > > However, 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? Absolutely not; this is a bug in your code (more exactly a missing call to g_io_channel_set_flags()); check the documentation for proper usage of this function. Also, application development questions should be raised on gtk-app-devel-list (and think of the vast amount of gtk+ based software out there, it's quite unlikely that you hit a massive bug like this). Regards, Sven -- Sven Herzberg Imendio AB - Expert solutions in GTK+ http://www.imendio.com _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
Re: Is this a bug of GMainLoop?> and think of the vast amount of gtk+ based software
> out there, it's quite unlikely that you hit a massive bug like this. I wouldn't be so sure actually. As far as I can see, Yu's sample program might well use GIOChannels and watches of them in a new way that hasn't been tested before... I am still debugging it and trying to understand what is actually going on. There might very well be some clear bug in giowin32.c that is triggered here. (But whether fixing that bug so that Yu's program works won't then cause some other program to fail is another thing...) (There are bug reports open against giowin32.c that contain patches even that I haven't had the courage to apply for the same reason...) That is the problem with the GIOChannel and main loop stuff on Windows; there are so many ways one can combine the calls that it is very hard to verify that everything that is supposed to work actually does. On Unix the GIOChannel and main loop implementations are much more straightforward, and it is likely that it works whatever innovative new way a programmer uses it... --tml _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
Re: Is this a bug of GMainLoop?Have you, by the way, verified that the corresponding program works on Linux?
--tml _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
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@... [mailto:tlillqvist@...] On Behalf Of Tor Lillqvist Sent: 星期四, 15 五月, 2008 AM 1:53 To: #YU KUAN# Cc: gtk-devel-list@... Subject: Re: Is this a bug of GMainLoop? Have you, by the way, verified that the corresponding program works on Linux? --tml _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
Re: Is this a bug of GMainLoop?> But I don't know whether it affects other part of glib program.
That is indeed the problem;) The code in giowin32.c is extremely fragile and somewhat ad-hoc. I spent several hours yesterday going over the debugging output, attempting small changes here and there. (I didn't come up with your suggested patch, but some similar ideas.) I will try your suggestion, too, and try to check whether it affects adversely the use patterns of GIOChannels and main loops in some other applications. --tml _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
Re: Is this a bug of GMainLoop?> I will try your suggestion, too, and try to check whether it affects
> adversely the use patterns of GIOChannels and main loops in some other > applications. As far as I could see briefly testing, Yu's patch didn't have any ill effects. I would love if more people could test it, though. (There was a slight glitch in the context of the patch in Yu's message, maybe a copy/paste error? I mean the line "channel->last_events = 1;" which actually is "channel->last_events = 0;" in the source.) Yu's patch, to *current* trunk giowin32.c (I just committed a change that improved the G_IO_WIN32_DEBUG output a bit) is as follows. Please test it, all who can. (It should be trivial to apply it manually to the glib-2-16 branch, too.) --tml Index: glib/giowin32.c =================================================================== --- glib/giowin32.c (revision 6898) +++ glib/giowin32.c (working copy) @@ -849,6 +849,13 @@ if (channel->debug) g_print ("\n setting last_events=0"); channel->last_events = 0; + + if ((event_mask & FD_WRITE) && !channel->write_would_have_blocked) + { + if (channel->debug) + g_print (" WSASetEvent(%#x)", watch->pollfd.fd); + WSASetEvent ((WSAEVENT) watch->pollfd.fd); + } } break; _______________________________________________ gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
|
|
Re: Is this a bug of GMainLoop?> Yu's patch, to *current* trunk giowin32.c (I just committed a change
> that improved the G_IO_WIN32_DEBUG output a bit) is as follows. Please > test it, all who can. (It should be trivial to apply it manually to > the glib-2-16 branch, too.) Hello, anyone ? Please... --tml > Index: glib/giowin32.c > =================================================================== > --- glib/giowin32.c (revision 6898) > +++ glib/giowin32.c (working copy) > @@ -849,6 +849,13 @@ > if (channel->debug) > g_print ("\n setting last_events=0"); > channel->last_events = 0; > + > + if ((event_mask & FD_WRITE) && !channel->write_would_have_blocked) > + { > + if (channel->debug) > + g_print (" WSASetEvent(%#x)", watch->pollfd.fd); > + WSASetEvent ((WSAEVENT) watch->pollfd.fd); > + } > } > break; > gtk-devel-list mailing list gtk-devel-list@... http://mail.gnome.org/mailman/listinfo/gtk-devel-list |
| Free Forum Powered by Nabble | Forum Help |