+++ /dev/null
-I managed to reproduce the problem you saw with gtk-vnc and windows
-hanging. With the glib IO debug turned up high I can see it is treating
-the FD as a file handle, rather than a socket - which is to be expected
-because gnulib is wrapping winsock to give back real FDs.
-
-Unfortunately glib is on crack, and for file handles it implements
-IO waits by having a background thread for each file handle that sits
-in a read/write call forever, and sets flags. To quote the docs
-
- "If you have created a GIOChannel for a file descriptor and started
- watching (polling) it, you shouldn't call read() on the file descriptor.
- This is because adding polling for a file descriptor is implemented in
- GLib on Windows by starting a thread that sits blocked in a read() from
- the file descriptor most of the time. All reads from the file descriptor
- should be done by this internal GLib thread. Your code should call only
- g_io_channel_read(). "
-
-This is just epic fail when combined with what we want todo. Making gtk-vnc
-use g_io_channel_read() instead didn't work either. I think the glib thread
-concept simply doesn't work for FDs which are aliases for sockets.
-
-So I've tried a atch which creates an IO channel using
-
- g_io_channel_win32_new_socket(_get_osfhandle(fd))
-
-to explicitly make glib treat it as a socket, and avoid the thread insanity.
-Slightly nasty because we're reversing gnulibs magic by translating the
-FD back into a socket, but empirically it seems to work better for me. I've
-not yet got it to hang with this patch.
-
-I also needed to make our read/write functions use the 'fd' in the gvnc
-struct, instead of fetching it from the IOChannel object.
-
-Let me know if this patch works for you too....
-
-Daniel
-
-diff --git a/src/gvnc.c b/src/gvnc.c
---- a/src/gvnc.c
-+++ b/src/gvnc.c
-@@ -347,7 +347,6 @@ static int gvnc_zread(struct gvnc *gvnc,
-
- static int gvnc_read(struct gvnc *gvnc, void *data, size_t len)
- {
-- int fd = g_io_channel_unix_get_fd(gvnc->channel);
- char *ptr = data;
- size_t offset = 0;
-
-@@ -380,7 +379,7 @@ static int gvnc_read(struct gvnc *gvnc,
- ret = -1;
- }
- } else
-- ret = recv (fd, gvnc->read_buffer, 4096, 0);
-+ ret = recv (gvnc->fd, gvnc->read_buffer, 4096, 0);
-
- if (ret == -1) {
- switch (errno) {
-@@ -422,7 +421,6 @@ static int gvnc_read(struct gvnc *gvnc,
-
- static void gvnc_flush(struct gvnc *gvnc)
- {
-- int fd = g_io_channel_unix_get_fd(gvnc->channel);
- size_t offset = 0;
- while (offset < gvnc->write_offset) {
- int ret;
-@@ -439,7 +437,7 @@ static void gvnc_flush(struct gvnc *gvnc
- ret = -1;
- }
- } else
-- ret = send (fd,
-+ ret = send (gvnc->fd,
- gvnc->write_buffer+offset,
- gvnc->write_offset-offset, 0);
- if (ret == -1) {
-@@ -490,11 +488,10 @@ static ssize_t gvnc_tls_push(gnutls_tran
- const void *data,
- size_t len) {
- struct gvnc *gvnc = (struct gvnc *)transport;
-- int fd = g_io_channel_unix_get_fd(gvnc->channel);
- int ret;
-
- retry:
-- ret = write(fd, data, len);
-+ ret = write(gvnc->fd, data, len);
- if (ret < 0) {
- if (errno == EINTR)
- goto retry;
-@@ -508,11 +505,10 @@ static ssize_t gvnc_tls_pull(gnutls_tran
- void *data,
- size_t len) {
- struct gvnc *gvnc = (struct gvnc *)transport;
-- int fd = g_io_channel_unix_get_fd(gvnc->channel);
- int ret;
-
- retry:
-- ret = read(fd, data, len);
-+ ret = read(gvnc->fd, data, len);
- if (ret < 0) {
- if (errno == EINTR)
- goto retry;
-@@ -2872,7 +2868,13 @@ gboolean gvnc_open_fd(struct gvnc *gvnc,
- if (!gvnc_set_nonblock(fd))
- return FALSE;
-
-- if (!(gvnc->channel = g_io_channel_unix_new(fd))) {
-+ if (!(gvnc->channel =
-+#ifdef WIN32
-+ g_io_channel_win32_new_socket(_get_osfhandle(fd))
-+#else
-+ g_io_channel_unix_new(fd)
-+#endif
-+ )) {
- GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
- return FALSE;
- }
-@@ -2917,7 +2919,13 @@ gboolean gvnc_open_host(struct gvnc *gvn
- if (!gvnc_set_nonblock(fd))
- break;
-
-- if (!(chan = g_io_channel_unix_new(fd))) {
-+ if (!(chan =
-+#ifdef WIN32
-+ g_io_channel_win32_new_socket(_get_osfhandle(fd))
-+#else
-+ g_io_channel_unix_new(fd)
-+#endif
-+ )) {
- close(fd);
- GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
- break;
-
---
-|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
-|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
-|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
-|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|