Bug 1227023 - Include the Gtk+3 version in update URL if available on Gtk+2 builds. r=karlt a=ritu
authorMike Hommey <mh+mozilla@glandium.org>
Mon, 21 Dec 2015 11:55:23 -0800
changeset 304080 432c275bd01cd62cc072f81a780a871249a50d03
parent 304079 abf1e06c22c999073d0311268572998ef49bcf61
child 304081 d48a8bf65a6b71bfc47f07cd4dee19921cfbf7cd
push id5415
push userkwierso@gmail.com
push dateMon, 21 Dec 2015 19:56:09 +0000
treeherdermozilla-beta@432c275bd01c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt, ritu
bugs1227023
milestone43.0
Bug 1227023 - Include the Gtk+3 version in update URL if available on Gtk+2 builds. r=karlt a=ritu Instead of giving the Gtk+2 version.
toolkit/xre/glxtest.cpp
xpcom/base/nsSystemInfo.cpp
--- a/toolkit/xre/glxtest.cpp
+++ b/toolkit/xre/glxtest.cpp
@@ -22,16 +22,20 @@
 #include <cstdio>
 #include <cstdlib>
 #include <unistd.h>
 #include <dlfcn.h>
 #include "nscore.h"
 #include <fcntl.h>
 #include "stdint.h"
 
+#if MOZ_WIDGET_GTK == 2
+#include <glib.h>
+#endif
+
 #ifdef __SUNPRO_CC
 #include <stdio.h>
 #endif
 
 #include "X11/Xlib.h"
 #include "X11/Xutil.h"
 
 #include "mozilla/unused.h"
@@ -65,16 +69,21 @@ extern int glxtest_pipe;
 // the PID of the glxtest process, to pass to waitpid()
 extern pid_t glxtest_pid;
 }
 }
 
 // the write end of the pipe, which we're going to write to
 static int write_end_of_the_pipe = -1;
 
+#if MOZ_WIDGET_GTK == 2
+static int gtk_write_end_of_the_pipe = -1;
+int gtk_read_end_of_the_pipe = -1;
+#endif
+
 // C++ standard collides with C standard in that it doesn't allow casting void* to function pointer types.
 // So the work-around is to convert first to size_t.
 // http://www.trilithium.com/johan/2004/12/problem-with-dlsym/
 template<typename func_ptr_type>
 static func_ptr_type cast(void *ptr)
 {
   return reinterpret_cast<func_ptr_type>(
            reinterpret_cast<size_t>(ptr)
@@ -115,16 +124,46 @@ void glxtest()
   // we want to redirect to /dev/null stdout, stderr, and while we're at it,
   // any PR logging file descriptors. To that effect, we redirect all positive
   // file descriptors up to what open() returns here. In particular, 1 is stdout and 2 is stderr.
   int fd = open("/dev/null", O_WRONLY);
   for (int i = 1; i < fd; i++)
     dup2(fd, i);
   close(fd);
 
+#if MOZ_WIDGET_GTK == 2
+  // On Gtk+2 builds, try to get the Gtk+3 version if it's installed, and
+  // use that in nsSystemInfo for secondaryLibrary. Better safe than sorry,
+  // we want to load the Gtk+3 library in a subprocess, and since we already
+  // have such a subprocess for the GLX test, we piggy back on it.
+  void *gtk3 = dlopen("libgtk-3.so.0", RTLD_LOCAL | RTLD_LAZY);
+  if (gtk3) {
+    auto gtk_get_major_version = reinterpret_cast<guint (*)(void)>(
+      dlsym(gtk3, "gtk_get_major_version"));
+    auto gtk_get_minor_version = reinterpret_cast<guint (*)(void)>(
+      dlsym(gtk3, "gtk_get_minor_version"));
+    auto gtk_get_micro_version = reinterpret_cast<guint (*)(void)>(
+      dlsym(gtk3, "gtk_get_micro_version"));
+
+    if (gtk_get_major_version && gtk_get_minor_version &&
+        gtk_get_micro_version) {
+      // 64 bytes is going to be well enough for "GTK " followed by 3 integers
+      // separated with dots.
+      char gtkver[64];
+      int len = snprintf(gtkver, sizeof(gtkver), "GTK %u.%u.%u",
+                         gtk_get_major_version(), gtk_get_minor_version(),
+                         gtk_get_micro_version());
+      if (len > 0 && size_t(len) < sizeof(gtkver)) {
+        mozilla::unused << write(gtk_write_end_of_the_pipe, gtkver, len);
+      }
+    }
+  }
+#endif
+
+
   if (getenv("MOZ_AVOID_OPENGL_ALTOGETHER"))
     fatal_error("The MOZ_AVOID_OPENGL_ALTOGETHER environment variable is defined");
 
   ///// Open libGL and load needed symbols /////
 #ifdef __OpenBSD__
   #define LIBGL_FILENAME "libGL.so"
 #else
   #define LIBGL_FILENAME "libGL.so.1"
@@ -259,30 +298,52 @@ void glxtest()
 /** \returns true in the child glxtest process, false in the parent process */
 bool fire_glxtest_process()
 {
   int pfd[2];
   if (pipe(pfd) == -1) {
       perror("pipe");
       return false;
   }
+#if MOZ_WIDGET_GTK == 2
+  int gtkpfd[2];
+  if (pipe(gtkpfd) == -1) {
+      perror("pipe");
+      return false;
+  }
+#endif
   pid_t pid = fork();
   if (pid < 0) {
       perror("fork");
       close(pfd[0]);
       close(pfd[1]);
+#if MOZ_WIDGET_GTK == 2
+      close(gtkpfd[0]);
+      close(gtkpfd[1]);
+#endif
       return false;
   }
   // The child exits early to avoid running the full shutdown sequence and avoid conflicting with threads 
   // we have already spawned (like the profiler).
   if (pid == 0) {
       close(pfd[0]);
       write_end_of_the_pipe = pfd[1];
+#if MOZ_WIDGET_GTK == 2
+      close(gtkpfd[0]);
+      gtk_write_end_of_the_pipe = gtkpfd[1];
+#endif
       glxtest();
       close(pfd[1]);
+#if MOZ_WIDGET_GTK == 2
+      close(gtkpfd[1]);
+#endif
       _exit(0);
   }
 
   close(pfd[1]);
   mozilla::widget::glxtest_pipe = pfd[0];
   mozilla::widget::glxtest_pid = pid;
+#if MOZ_WIDGET_GTK == 2
+  close(gtkpfd[1]);
+  gtk_read_end_of_the_pipe = gtkpfd[0];
+#endif
   return false;
 }
--- a/xpcom/base/nsSystemInfo.cpp
+++ b/xpcom/base/nsSystemInfo.cpp
@@ -674,22 +674,41 @@ nsSystemInfo::Init()
   if (NS_SUCCEEDED(GetSelectedCityInfo(countryCode))) {
     rv = SetPropertyAsAString(NS_LITERAL_STRING("countryCode"), countryCode);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 #endif
 
 #if defined(MOZ_WIDGET_GTK)
   // This must be done here because NSPR can only separate OS's when compiled, not libraries.
-  char* gtkver = PR_smprintf("GTK %u.%u.%u", gtk_major_version,
-                             gtk_minor_version, gtk_micro_version);
-  if (gtkver) {
+  // 64 bytes is going to be well enough for "GTK " followed by 3 integers
+  // separated with dots.
+  char gtkver[64];
+  ssize_t gtkver_len = 0;
+
+#if MOZ_WIDGET_GTK == 2
+  extern int gtk_read_end_of_the_pipe;
+
+  if (gtk_read_end_of_the_pipe != -1) {
+    do {
+      gtkver_len = read(gtk_read_end_of_the_pipe, &gtkver, sizeof(gtkver));
+    } while (gtkver_len < 0 && errno == EINTR);
+    close(gtk_read_end_of_the_pipe);
+  }
+#endif
+
+  if (gtkver_len <= 0) {
+    gtkver_len = snprintf(gtkver, sizeof(gtkver), "GTK %u.%u.%u",
+                          gtk_major_version, gtk_minor_version,
+                          gtk_micro_version);
+  }
+
+  if (gtkver_len > 0) {
     rv = SetPropertyAsACString(NS_LITERAL_STRING("secondaryLibrary"),
-                               nsDependentCString(gtkver));
-    PR_smprintf_free(gtkver);
+                               nsDependentCString(gtkver, gtkver_len));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 #endif
 
 #ifdef MOZ_WIDGET_ANDROID
   if (mozilla::AndroidBridge::Bridge()) {