Bug 1227023 - Include the Gtk+3 version in update URL if available on Gtk+2 builds. r=karlt
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 04 Dec 2015 09:12:39 +0900
changeset 309913 139130c7ed7aa617f92abd31b5a89fcc582dc7b8
parent 309912 fa84e8d2340b304f6584438e5b2145f304ccbfed
child 309914 30044858f40c18b5059a0df89ab18eb455270286
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1227023
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1227023 - Include the Gtk+3 version in update URL if available on Gtk+2 builds. r=karlt 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
@@ -675,22 +675,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
   AndroidSystemInfo info;