Package: vinagre
Version: 3.4.2-1
Severity: important
Tags: upstream patch
Control: forwarded -1 https://bugzilla.gnome.org/show_bug.cgi?id=690449

Dear Maintainers,

Tunneling VNC connections through SSH does not work. After clicking the
"Connect" button, Vinagre waits a dozen of seconds, then fails with "Connection
to host $HOST was closed".

I identified the cause of the problem as being a blocking read (which ought to
be non-blocking). I attach a patch that fixes the problem for me, and that I
have forwarded upstream.

Cheers,

-- System Information:
Debian Release: wheezy/sid
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)

Kernel: Linux 3.2.0-4-amd64 (SMP w/2 CPU cores)
Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash

Versions of packages vinagre depends on:
ii  dconf-gsettings-backend [gsettings-backend]  0.12.1-3
ii  libavahi-common3                             0.6.31-1
ii  libavahi-gobject0                            0.6.31-1
ii  libavahi-ui-gtk3-0                           0.6.31-1
ii  libc6                                        2.13-37
ii  libcairo2                                    1.12.2-2
ii  libdbus-glib-1-2                             0.100-1
ii  libgdk-pixbuf2.0-0                           2.26.1-1
ii  libglib2.0-0                                 2.33.12+really2.32.4-3
ii  libgnome-keyring0                            3.4.1-1
ii  libgtk-3-0                                   3.4.2-4
ii  libgtk-vnc-2.0-0                             0.5.0-3
ii  libtelepathy-glib0                           0.18.2-2
ii  libvte-2.90-9                                1:0.32.2-1
ii  libxml2                                      2.8.0+dfsg1-7

Versions of packages vinagre recommends:
ii  gnome-icon-theme  3.4.0-2
ii  rdesktop          1.7.1-1

vinagre suggests no packages.

-- no debconf information
Description: Fix VNC tunneling through SSH
 Use GPollableInputStream when checking for SSH errors. Otherwise the read on
 stderr blocks, causing the SSH connection to timeout.
 .
 The original code sets O_NONBLOCK on stderr, but this does not work. This flag
 is not propagated to the corresponding GDataInputStream (at least with glib >=
 2.32; it may have worked with older versions).
 .
 As a side effect, the patch fixes a minor memory leak in
 vinagre-ssh.c:look_for_stderr_errors() where the "line" variable was not
 correctly freed in all cases.
Author: Sébastien Villemot <[email protected]>
Bug: https://bugzilla.gnome.org/show_bug.cgi?id=690449
Last-Update: 2012-12-25
---
This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
--- a/vinagre/vinagre-ssh.c
+++ b/vinagre/vinagre-ssh.c
@@ -667,17 +667,30 @@
 }
 
 static gboolean
-look_for_stderr_errors (GDataInputStream *error_stream, GError **error)
+look_for_stderr_errors (GInputStream *is, GError **error)
 {
-  char *line;
+  GDataInputStream *error_stream;
+  char *line = NULL;
+  gboolean ret;
+
+  error_stream = g_data_input_stream_new (is);
 
   while (1)
     {
+#ifndef G_OS_WIN32
+      if (!g_pollable_input_stream_is_readable (G_POLLABLE_INPUT_STREAM (is)))
+        {
+          ret = TRUE;
+          break;
+        }
+#endif
+
       line = g_data_input_stream_read_line (error_stream, NULL, NULL, NULL);
 
       if (line == NULL)
         {
-          return TRUE;
+          ret = TRUE;
+          break;
         }
     
       if (strstr (line, "Permission denied") != NULL)
@@ -685,41 +698,49 @@
           g_set_error_literal (error,
 	                       VINAGRE_SSH_ERROR, VINAGRE_SSH_ERROR_PERMISSION_DENIED,
         	               _("Permission denied"));
-          return FALSE;
+          ret = FALSE;
+          break;
         }
       else if (strstr (line, "Name or service not known") != NULL)
         {
           g_set_error_literal (error,
 	                       VINAGRE_SSH_ERROR, VINAGRE_SSH_ERROR_HOST_NOT_FOUND,
         	               _("Hostname not known"));
-          return FALSE;
+          ret = FALSE;
+          break;
         }
       else if (strstr (line, "No route to host") != NULL)
         {
           g_set_error_literal (error,
 	                       VINAGRE_SSH_ERROR, VINAGRE_SSH_ERROR_HOST_NOT_FOUND,
         	               _("No route to host"));
-          return FALSE;
+          ret = FALSE;
+          break;
         }
       else if (strstr (line, "Connection refused") != NULL)
         {
           g_set_error_literal (error,
 	                       VINAGRE_SSH_ERROR, VINAGRE_SSH_ERROR_PERMISSION_DENIED,
         	               _("Connection refused by server"));
-          return FALSE;
+          ret = FALSE;
+          break;
         }
       else if (strstr (line, "Host key verification failed") != NULL) 
         {
           g_set_error_literal (error,
 	                       VINAGRE_SSH_ERROR, VINAGRE_SSH_ERROR_FAILED,
         	               _("Host key verification failed"));
-          return FALSE;
+          ret = FALSE;
+          break;
         }
       
-      g_free (line);
     }
 
-  return TRUE;
+  if (line)
+    g_free (line);
+
+  g_object_unref (error_stream);
+  return ret;
 }
 
 gboolean
@@ -737,7 +758,6 @@
   gchar *user, *host, **args;
   gboolean res;
   GInputStream *is;
-  GDataInputStream *error_stream;
 
   if (!hostname)
     return FALSE;
@@ -791,14 +811,12 @@
   ioctlsocket (stderr_fd, FIONBIO, &mode);
   is = g_win32_input_stream_new (stderr_fd, FALSE);
 #else /* !G_OS_WIN32 */
-  fcntl (stderr_fd, F_SETFL, O_NONBLOCK | fcntl (stderr_fd, F_GETFL));
   is = g_unix_input_stream_new (stderr_fd, FALSE);
 #endif /* G_OS_WIN32 */
-  error_stream = g_data_input_stream_new (is);
-  g_object_unref (is);
   
-  res = look_for_stderr_errors (error_stream, error);
-  g_object_unref (error_stream);
+  res = look_for_stderr_errors (is, error);
+
+  g_object_unref (is);
 
   if (!res)
     return FALSE;

Reply via email to