Package: gnome-session Version: 2.18.2-1 Severity: important Tags: patch
Since the upgrade to 2.18, I had been plagued by gnome-session hanging on startup of any 'non-trivial' session. Attaching gdb showed the hang to be a deadlock because it crashed somewhere inside the glibc memory management code, and the signal handler tried to use memory management functions as well, so it hung waiting for the glibc internal memory management mutex. After a long debugging session chasing countless red herrings, I finally tracked down the cause of the crash. update_trans_effect could end up using stale icon dimensions, so it would write beyond the end of the memory allocated for the pixel data. The attached patch fixes this. --- System information. --- Architecture: powerpc Kernel: Linux 2.6.21-1-powerpc Debian Release: lenny/sid 500 unstable mirror.switch.ch 500 stable security.debian.org 102 experimental ftp.ch.debian.org --- Package information. --- Depends (Version) | Installed ======================================-+-============== libatk1.0-0 (>= 1.13.2) | 1.18.0-2 libbonobo2-0 (>= 2.15.0) | 2.18.0-2 libc6 (>= 2.5-5) | 2.5-11 libdbus-1-3 (>= 0.94) | 1.1.1-1 libdbus-glib-1-2 (>= 0.73) | 0.73-2 libesd0 (>= 0.2.35) | OR libesd-alsa0 (>= 0.2.35) | 0.2.36-3 libgconf2-4 (>= 2.13.5) | 2.18.0.1-3 libglib2.0-0 (>= 2.12.9) | 2.12.12-1 libgnome-desktop-2 (>= 2.11.1) | 2.18.2-1 libgnome-keyring0 (>= 0.8) | 0.8.1-2 libgnome2-0 (>= 2.17.3) | 2.18.0-4 libgnomeui-0 (>= 2.17.1) | 2.18.1-2 libgtk2.0-0 (>= 2.10.3) | 2.10.13-1 libice6 (>= 1:1.0.0) | 1:1.0.3-2 liborbit2 (>= 1:2.14.1) | 1:2.14.7-0.1 libpango1.0-0 (>= 1.16.4) | 1.16.4-1 libsm6 | 2:1.0.3-1 libwrap0 | 7.6.dbs-13 libx11-6 | 2:1.1.2-1 libxau6 | 1:1.0.3-2 libxrandr2 (>= 2:1.2.0) | 2:1.2.1-1 gconf2 (>= 2.12.1-1) | 2.18.0.1-3 gnome-control-center (>= 1:2.18) | 1:2.18.1-1 gnome-control-center (<< 1:2.19) | 1:2.18.1-1 -- Earthling Michel Dänzer | http://tungstengraphics.com Libre software enthusiast | Debian, X and DRI developer
--- gnome-session-2.18.2.orig/gnome-session/splash-widget.c 2007-05-28 13:41:45.000000000 +0200 +++ gnome-session-2.18.2/gnome-session/splash-widget.c 2007-06-25 20:34:32.000000000 +0200 @@ -74,13 +74,6 @@ typedef struct { typedef struct { SplashWidget *sw; SplashIcon *si; - int width; - int height; - int n_channels; - int rowstride_trans; - int rowstride_orig; - guchar *pixels_trans; - guchar *pixels_orig; } TransParam; static gboolean @@ -485,6 +478,13 @@ layout_icon (SplashWidget *sw, SplashIco si->scaled = gdk_pixbuf_scale_simple ( si->unscaled, sw->icon_size, sw->icon_size, GDK_INTERP_BILINEAR); + + if (!gdk_pixbuf_get_has_alpha (si->scaled)) { + si->scaled_copy = gdk_pixbuf_add_alpha (si->scaled, FALSE, 0, 0, 0); + g_object_unref (si->scaled); + si->scaled = gdk_pixbuf_copy (si->scaled_copy); + } else + si->scaled_copy = gdk_pixbuf_copy (si->scaled); } if (sw->cur_x_offset >= (sw->image_bounds.width - SPLASH_ICON_BORDER * 2 - @@ -576,32 +576,19 @@ splash_widget_add_icon (SplashWidget *sw si = g_new0 (SplashIcon, 1); si->unscaled = pb; + layout_icon (sw, si, &area); + sw->icons = g_list_append (sw->icons, si); - layout_icon (sw, si, &area); - /* prepare transparency effect */ if ((gdk_pixbuf_get_colorspace (si->scaled) == GDK_COLORSPACE_RGB) && (gdk_pixbuf_get_bits_per_sample (si->scaled) == 8) && (gdk_pixbuf_get_n_channels (si->scaled))) { si->trans_count = 0; - if (!gdk_pixbuf_get_has_alpha (si->scaled)) { - si->scaled_copy = gdk_pixbuf_add_alpha (si->scaled, FALSE, 0, 0, 0); - g_object_unref (si->scaled); - si->scaled = gdk_pixbuf_copy (si->scaled_copy); - } else - si->scaled_copy = gdk_pixbuf_copy (si->scaled); tp = g_new0(TransParam, 1); tp->si = si; tp->sw = sw; - tp->width = gdk_pixbuf_get_width (tp->si->scaled); - tp->height = gdk_pixbuf_get_height (tp->si->scaled); - tp->rowstride_trans = gdk_pixbuf_get_rowstride (tp->si->scaled); - tp->rowstride_orig = gdk_pixbuf_get_rowstride (tp->si->scaled_copy); - tp->pixels_trans = gdk_pixbuf_get_pixels (tp->si->scaled); - tp->pixels_orig = gdk_pixbuf_get_pixels (tp->si->scaled_copy); - tp->n_channels = gdk_pixbuf_get_n_channels (tp->si->scaled); gdk_pixbuf_fill (si->scaled, 0x00000000); g_timeout_add (TRANS_TIMEOUT, update_trans_effect, tp); @@ -624,6 +611,13 @@ update_trans_effect (gpointer trans_para gdouble r_mul, g_mul, b_mul, a_mul; gint x = 0; gint y = 0; + gint width = 0; + gint height = 0; + int n_channels; + int rowstride_trans; + int rowstride_orig; + guchar *pixels_trans; + guchar *pixels_orig; TransParam *tp = (TransParam *) trans_param; @@ -645,10 +639,18 @@ update_trans_effect (gpointer trans_para g_mul = 1; b_mul = 1; - for (y = 0; y < tp->height; y++) { - for (x = 0; x < tp->width; x++) { - p_trans = tp->pixels_trans + y * tp->rowstride_trans + x * tp->n_channels; - p_orig = tp->pixels_orig + y * tp->rowstride_orig + x * tp->n_channels; + rowstride_trans = gdk_pixbuf_get_rowstride (tp->si->scaled); + rowstride_orig = gdk_pixbuf_get_rowstride (tp->si->scaled_copy); + pixels_trans = gdk_pixbuf_get_pixels (tp->si->scaled); + pixels_orig = gdk_pixbuf_get_pixels (tp->si->scaled_copy); + n_channels = gdk_pixbuf_get_n_channels (tp->si->scaled); + width = gdk_pixbuf_get_width (tp->si->scaled); + height = gdk_pixbuf_get_height (tp->si->scaled); + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + p_trans = pixels_trans + y * rowstride_trans + x * n_channels; + p_orig = pixels_orig + y * rowstride_orig + x * n_channels; /* we can add more effects here apart from alpha fading */ p_trans[0] = r_mul * p_orig[0];