Don't build dbus either.
[fedora-mingw.git] / gtk-vnc / gtk-vnc-dan-fd-fix.patch
1 I managed to reproduce the problem you saw with gtk-vnc and windows
2 hanging. With the glib IO debug turned up high I can see it is treating
3 the FD as a file handle, rather than a socket - which is to be expected
4 because gnulib is wrapping winsock to give back real FDs.
5
6 Unfortunately glib is on crack, and for file handles it implements
7 IO waits by having a background thread for each file handle that sits
8 in a read/write call forever, and sets flags. To quote the docs
9
10   "If you have created a GIOChannel for a file descriptor and started 
11    watching (polling) it, you shouldn't call read() on the file descriptor.
12    This is because adding polling for a file descriptor is implemented in 
13    GLib on Windows by starting a thread that sits blocked in a read() from
14    the file descriptor most of the time. All reads from the file descriptor 
15    should be done by this internal GLib thread. Your code should call only 
16    g_io_channel_read(). "
17
18 This is just epic fail when combined with what we want todo. Making gtk-vnc
19 use g_io_channel_read() instead didn't work either. I think the glib thread
20 concept simply doesn't work for FDs which are aliases for sockets.
21
22 So I've tried a atch which creates an IO channel using 
23
24   g_io_channel_win32_new_socket(_get_osfhandle(fd))
25
26 to explicitly make glib treat it as a socket, and avoid the thread insanity.
27 Slightly nasty because we're reversing gnulibs magic by translating the
28 FD back into a socket, but empirically it seems to work better for me. I've
29 not yet got it  to hang with this patch.
30
31 I also needed to make our read/write functions use the 'fd' in the gvnc
32 struct, instead of fetching it from the IOChannel object.
33
34 Let me know if this patch works for you too....
35
36 Daniel
37
38 diff --git a/src/gvnc.c b/src/gvnc.c
39 --- a/src/gvnc.c
40 +++ b/src/gvnc.c
41 @@ -347,7 +347,6 @@ static int gvnc_zread(struct gvnc *gvnc,
42  
43  static int gvnc_read(struct gvnc *gvnc, void *data, size_t len)
44  {
45 -       int fd = g_io_channel_unix_get_fd(gvnc->channel);
46         char *ptr = data;
47         size_t offset = 0;
48  
49 @@ -380,7 +379,7 @@ static int gvnc_read(struct gvnc *gvnc, 
50                                         ret = -1;
51                                 }
52                         } else
53 -                               ret = recv (fd, gvnc->read_buffer, 4096, 0);
54 +                               ret = recv (gvnc->fd, gvnc->read_buffer, 4096, 0);
55  
56                         if (ret == -1) {
57                                 switch (errno) {
58 @@ -422,7 +421,6 @@ static int gvnc_read(struct gvnc *gvnc, 
59  
60  static void gvnc_flush(struct gvnc *gvnc)
61  {
62 -       int fd = g_io_channel_unix_get_fd(gvnc->channel);
63         size_t offset = 0;
64         while (offset < gvnc->write_offset) {
65                 int ret;
66 @@ -439,7 +437,7 @@ static void gvnc_flush(struct gvnc *gvnc
67                                 ret = -1;
68                         }
69                 } else
70 -                       ret = send (fd,
71 +                       ret = send (gvnc->fd,
72                                     gvnc->write_buffer+offset,
73                                     gvnc->write_offset-offset, 0);
74                 if (ret == -1) {
75 @@ -490,11 +488,10 @@ static ssize_t gvnc_tls_push(gnutls_tran
76                               const void *data,
77                               size_t len) {
78         struct gvnc *gvnc = (struct gvnc *)transport;
79 -       int fd = g_io_channel_unix_get_fd(gvnc->channel);
80         int ret;
81  
82   retry:
83 -       ret = write(fd, data, len);
84 +       ret = write(gvnc->fd, data, len);
85         if (ret < 0) {
86                 if (errno == EINTR)
87                         goto retry;
88 @@ -508,11 +505,10 @@ static ssize_t gvnc_tls_pull(gnutls_tran
89                              void *data,
90                              size_t len) {
91         struct gvnc *gvnc = (struct gvnc *)transport;
92 -       int fd = g_io_channel_unix_get_fd(gvnc->channel);
93         int ret;
94  
95   retry:
96 -       ret = read(fd, data, len);
97 +       ret = read(gvnc->fd, data, len);
98         if (ret < 0) {
99                 if (errno == EINTR)
100                         goto retry;
101 @@ -2872,7 +2868,13 @@ gboolean gvnc_open_fd(struct gvnc *gvnc,
102         if (!gvnc_set_nonblock(fd))
103                 return FALSE;
104  
105 -       if (!(gvnc->channel = g_io_channel_unix_new(fd))) {
106 +       if (!(gvnc->channel =
107 +#ifdef WIN32
108 +             g_io_channel_win32_new_socket(_get_osfhandle(fd))
109 +#else
110 +             g_io_channel_unix_new(fd)
111 +#endif
112 +             )) {
113                 GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
114                 return FALSE;
115         }
116 @@ -2917,7 +2919,13 @@ gboolean gvnc_open_host(struct gvnc *gvn
117                 if (!gvnc_set_nonblock(fd))
118                         break;
119  
120 -                if (!(chan = g_io_channel_unix_new(fd))) {
121 +                if (!(chan =
122 +#ifdef WIN32
123 +                     g_io_channel_win32_new_socket(_get_osfhandle(fd))
124 +#else
125 +                     g_io_channel_unix_new(fd)
126 +#endif
127 +                     )) {
128                          close(fd);
129                          GVNC_DEBUG ("Failed to g_io_channel_unix_new()\n");
130                          break;
131
132 -- 
133 |: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
134 |: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
135 |: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
136 |: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|