summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Worth <cworth@cworth.org>2005-08-01 13:33:47 +0000
committerCarl Worth <cworth@cworth.org>2005-08-01 13:33:47 +0000
commitc525c684ca712c5c5acd5431ec061bfab364cef5 (patch)
tree1058f354f0d420bb8e66e2604776806e9bbcd198
parent480951827e567db89f88e71e7ba20f4fa4633c1b (diff)
New public header file.
New function to reset all static data (eg. caches) to their initial state. Fix check-valgrind target to depend on the 'all' target. Add check for a new, proposed, XrmFinalize function. Add cairo-debug.c. Move the definition of CAIRO_BEGIN_DECLS to cairo-features.h so that it can be shared between public header files, and so that it doesn't clutter cairo.h Implement reset_static_data in all modules as required. Call cairo_debug_reset_static_data and FcFini so that we can have all tests be valgrind-clean with respect to memory leaks and still-reachable data.
-rw-r--r--ChangeLog55
-rw-r--r--Makefile.am3
-rw-r--r--configure.in7
-rw-r--r--src/Makefile.am1
-rw-r--r--src/cairo-debug.c73
-rw-r--r--src/cairo-debug.h48
-rw-r--r--src/cairo-features.h.in8
-rw-r--r--src/cairo-font.c39
-rw-r--r--src/cairo-ft-font.c13
-rw-r--r--src/cairo-xlib-screen.c53
-rw-r--r--src/cairo-xlib-surface.c26
-rw-r--r--src/cairo.h8
-rw-r--r--src/cairoint.h13
-rw-r--r--test/cairo-test.c6
-rw-r--r--test/cairo-test.h1
-rw-r--r--test/xlib-surface.c2
16 files changed, 329 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index d819ca9a..055550a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,45 @@
+2005-08-01 Carl Worth <cworth@cworth.org>
+
+ * src/cairo-debug.h: New public header file.
+
+ * src/cairo-debug.c: (cairo_debug_reset_static_data): New function
+ to reset all static data (eg. caches) to their initial state.
+
+ * Makefile.am: Fix check-valgrind target to depend on the 'all'
+ target.
+
+ * configure.in: Add check for a new, proposed, XrmFinalize
+ function.
+
+ * src/Makefile.am: Add cairo-debug.c.
+
+ * src/cairo.h:
+ * src/cairo-features.h.in: Move the definition of
+ CAIRO_BEGIN_DECLS to cairo-features.h so that it can be shared
+ between public header files, and so that it doesn't clutter
+ cairo.h
+
+ * src/cairoint.h:
+ * src/cairo-font.c: (_get_global_simple_cache),
+ (_get_outer_font_cache), (_get_inner_font_cache),
+ (_cairo_unlock_global_image_glyph_cache),
+ (_cairo_font_reset_static_data):
+ * src/cairo-ft-font.c: (_cairo_ft_font_reset_static_data):
+ * src/cairo-xlib-screen.c: (_cairo_xlib_close_display),
+ (_cairo_xlib_screen_info_reset),
+ (_cairo_xlib_screen_reset_static_data):
+ * src/cairo-xlib-surface.c: (_unlock_xlib_glyphset_caches),
+ (_destroy_glyphset_cache_recurse),
+ (_cairo_xlib_surface_reset_static_data): Implement
+ reset_static_data in all modules as required.
+
+ * test/xlib-surface.c: (main):
+ * test/cairo-test.h:
+ * test/cairo-test.c: (cairo_test_for_target),
+ (cairo_test_expecting): Call cairo_debug_reset_static_data and
+ FcFini so that we can have all tests be valgrind-clean with
+ respect to memory leaks and still-reachable data.
+
2005-08-01 Owen Taylor <otaylor@redhat.com>
* src/cairo.h src/cairoint.h src/cairo-surface.c:
@@ -642,6 +684,19 @@
2005-07-18 Carl Worth <cworth@cworth.org>
+ * test/.valgrind-suppressions: Add valgrind suppressions for
+ libpng/libz use of uninitialized data. There are clearly bugs here
+ that are not cairo's fault as zeroing the buffer before writing
+ the png image actually causes more errors(!). And, notably,
+ setting all the data to random bytes usually makes the errors go
+ away.
+
+ * test/Makefile.am: Change the check-valgrind target to include
+ the .valgrind-suppresions file and to tee output into
+ valgrind.log.
+
+2005-07-18 Carl Worth <cworth@cworth.org>
+
* configure.in: Add -head to CAIRO_VERSION after tagging with
SNAPSHOT_0_5_2.
diff --git a/Makefile.am b/Makefile.am
index c2a9965a..e375b1b1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,6 +15,9 @@ EXTRA_DIST = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = cairo.pc
+check-valgrind: all
+ $(MAKE) -C test check-valgrind
+
DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc
# Some custom targets to make it easier to release things.
diff --git a/configure.in b/configure.in
index 807d7e34..656db948 100644
--- a/configure.in
+++ b/configure.in
@@ -61,6 +61,13 @@ if test "x$use_xlib" = "xyes"; then
XRENDER_LIBS="$X_LIBS -lXrender -lXext -lX11 $X_EXTRA_LIBS"
use_xlib=yes], [
use_xlib="no (requires Xrender http://freedesktop.org/Software/xlibs)"])])
+ save_cflags="$CFLAGS"
+ save_libs="$LIBS"
+ CFLAGS="$CFLAGS $XRENDER_CFLAGS"
+ LIBS="$LIBS $XRENDER_LIBS"
+ AC_CHECK_FUNCS(XrmFinalize)
+ CFLAGS="$save_cflags"
+ LIBS="$save_libs"
fi
AM_CONDITIONAL(CAIRO_HAS_XLIB_SURFACE, test "x$use_xlib" = "xyes")
diff --git a/src/Makefile.am b/src/Makefile.am
index 16cbb1c5..4456bdc9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -86,6 +86,7 @@ libcairo_la_SOURCES = \
cairo-array.c \
cairo-cache.c \
cairo-color.c \
+ cairo-debug.c \
cairo-fixed.c \
cairo-font.c \
cairo-font-options.c \
diff --git a/src/cairo-debug.c b/src/cairo-debug.c
new file mode 100644
index 00000000..31eefc5a
--- /dev/null
+++ b/src/cairo-debug.c
@@ -0,0 +1,73 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ */
+
+#include "cairoint.h"
+
+/**
+ * cairo_debug_reset_static_data:
+ *
+ * Resets all static data within cairo to its original state,
+ * (ie. identical to the state at the time of program invocation). For
+ * example, all caches within cairo will be flushed empty.
+ *
+ * This function is intended to be useful when using memory-checking
+ * tools such as valgrind. When valgrind's memcheck analyzes a
+ * cairo-using program without a call to cairo_debug_reset_static_data,
+ * it will report all data reachable via cairo's static objects as
+ * "still reachable". Calling cairo_debug_reset_static_data just prior
+ * to program termination will make it easier to get squeaky clean
+ * reports from valgrind.
+ *
+ * WARNING: It is only safe to call this function when there are no
+ * active cairo objects remaining, (ie. the appropriate destroy
+ * functions have been called as necessary). If there are active cairo
+ * objects, this call is likely to cause a crash, (eg. an assertion
+ * failure due to a hash table being destroyed when non-empty).
+ **/
+void
+cairo_debug_reset_static_data (void)
+{
+#if CAIRO_HAS_XLIB_SURFACE
+ _cairo_xlib_surface_reset_static_data ();
+ _cairo_xlib_screen_reset_static_data ();
+#endif
+
+ _cairo_font_reset_static_data ();
+
+#if CAIRO_HAS_FT_FONT
+ _cairo_ft_font_reset_static_data ();
+#endif
+}
+
diff --git a/src/cairo-debug.h b/src/cairo-debug.h
new file mode 100644
index 00000000..1dab2c74
--- /dev/null
+++ b/src/cairo-debug.h
@@ -0,0 +1,48 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ * Carl D. Worth <cworth@cworth.org>
+ */
+
+#ifndef CAIRO_DEBUG_H
+#define CAIRO_DEBUG_H
+
+#include <cairo-features.h>
+
+CAIRO_BEGIN_DECLS
+
+void
+cairo_debug_reset_static_data (void);
+
+CAIRO_END_DECLS
+
+#endif /* CAIRO_H */
diff --git a/src/cairo-features.h.in b/src/cairo-features.h.in
index 8065be35..fdc1e37e 100644
--- a/src/cairo-features.h.in
+++ b/src/cairo-features.h.in
@@ -37,6 +37,14 @@
#ifndef CAIRO_FEATURES_H
#define CAIRO_FEATURES_H
+#ifdef __cplusplus
+# define CAIRO_BEGIN_DECLS extern "C" {
+# define CAIRO_END_DECLS }
+#else
+# define CAIRO_BEGIN_DECLS
+# define CAIRO_END_DECLS
+#endif
+
@PS_SURFACE_FEATURE@
@PDF_SURFACE_FEATURE@
diff --git a/src/cairo-font.c b/src/cairo-font.c
index 022be7da..dc34ef61 100644
--- a/src/cairo-font.c
+++ b/src/cairo-font.c
@@ -233,11 +233,11 @@ _unlock_global_simple_cache (void)
CAIRO_MUTEX_UNLOCK (_global_simple_cache_mutex);
}
+static cairo_cache_t *global_simple_cache = NULL;
+
static cairo_cache_t *
_get_global_simple_cache (void)
{
- static cairo_cache_t *global_simple_cache = NULL;
-
if (global_simple_cache == NULL)
{
global_simple_cache = malloc (sizeof (cairo_cache_t));
@@ -564,11 +564,11 @@ _unlock_global_font_cache (void)
CAIRO_MUTEX_UNLOCK (_global_font_cache_mutex);
}
+static cairo_cache_t *outer_font_cache = NULL;
+
static cairo_cache_t *
_get_outer_font_cache (void)
{
- static cairo_cache_t *outer_font_cache = NULL;
-
if (outer_font_cache == NULL)
{
outer_font_cache = malloc (sizeof (cairo_cache_t));
@@ -589,11 +589,11 @@ _get_outer_font_cache (void)
return NULL;
}
+static cairo_cache_t *inner_font_cache = NULL;
+
static cairo_cache_t *
_get_inner_font_cache (void)
{
- static cairo_cache_t *inner_font_cache = NULL;
-
if (inner_font_cache == NULL)
{
inner_font_cache = malloc (sizeof (cairo_cache_t));
@@ -1352,8 +1352,10 @@ _cairo_lock_global_image_glyph_cache()
void
_cairo_unlock_global_image_glyph_cache()
{
- _cairo_cache_shrink_to (_global_image_glyph_cache,
- CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT);
+ if (_global_image_glyph_cache) {
+ _cairo_cache_shrink_to (_global_image_glyph_cache,
+ CAIRO_IMAGE_GLYPH_CACHE_MEMORY_DEFAULT);
+ }
CAIRO_MUTEX_UNLOCK (_global_image_glyph_cache_mutex);
}
@@ -1380,3 +1382,24 @@ _cairo_get_global_image_glyph_cache ()
_global_image_glyph_cache = NULL;
return NULL;
}
+
+void
+_cairo_font_reset_static_data (void)
+{
+ _lock_global_font_cache ();
+ _cairo_cache_destroy (outer_font_cache);
+ outer_font_cache = NULL;
+ _cairo_cache_destroy (inner_font_cache);
+ inner_font_cache = NULL;
+ _unlock_global_font_cache ();
+
+ _cairo_lock_global_image_glyph_cache();
+ _cairo_cache_destroy (_global_image_glyph_cache);
+ _global_image_glyph_cache = NULL;
+ _cairo_unlock_global_image_glyph_cache();
+
+ _lock_global_simple_cache ();
+ _cairo_cache_destroy (global_simple_cache);
+ global_simple_cache = NULL;
+ _unlock_global_simple_cache ();
+}
diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 4a142b9d..fd16e071 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -2440,3 +2440,16 @@ _cairo_ft_unscaled_font_unlock_face (cairo_unscaled_font_t *unscaled_font)
{
_ft_unscaled_font_unlock_face ((ft_unscaled_font_t *)unscaled_font);
}
+
+void
+_cairo_ft_font_reset_static_data (void)
+{
+ _lock_global_ft_cache ();
+ if (_global_ft_cache) {
+ FT_Done_FreeType (_global_ft_cache->lib);
+ _global_ft_cache->lib = NULL;
+ }
+ _cairo_cache_destroy (&_global_ft_cache->base);
+ _global_ft_cache = NULL;
+ _unlock_global_ft_cache ();
+}
diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c
index 6a4efdbd..e71d10ec 100644
--- a/src/cairo-xlib-screen.c
+++ b/src/cairo-xlib-screen.c
@@ -245,34 +245,59 @@ _cairo_xlib_init_screen_font_options (cairo_xlib_screen_info_t *info)
CAIRO_MUTEX_DECLARE(_xlib_screen_mutex);
-static cairo_xlib_screen_info_t *_cairo_xlib_screen_list;
+static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
static int
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
{
- cairo_xlib_screen_info_t *info;
- cairo_xlib_screen_info_t **prev;
+ cairo_xlib_screen_info_t *info, *prev;
/*
* Unhook from the global list
*/
CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
- for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next) {
+ prev = NULL;
+ for (info = _cairo_xlib_screen_list; info; info = info->next) {
if (info->display == dpy) {
- *prev = info->next;
+ if (prev)
+ prev->next = info->next;
+ else
+ _cairo_xlib_screen_list = info->next;
free (info);
- if (!*prev)
- break;
+ break;
}
+ prev = info;
}
CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
-
+
+ /* Return value in accordance with requirements of
+ * XESetCloseDisplay */
return 0;
}
+static void
+_cairo_xlib_screen_info_reset (void)
+{
+ cairo_xlib_screen_info_t *info, *next;
+
+ /*
+ * Delete everything in the list.
+ */
+ CAIRO_MUTEX_LOCK (_xlib_screen_mutex);
+
+ for (info = _cairo_xlib_screen_list; info; info = next) {
+ next = info->next;
+ free (info);
+ }
+
+ _cairo_xlib_screen_list = NULL;
+
+ CAIRO_MUTEX_UNLOCK (_xlib_screen_mutex);
+
+}
-cairo_private cairo_xlib_screen_info_t *
+cairo_xlib_screen_info_t *
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
{
cairo_xlib_screen_info_t *info;
@@ -344,3 +369,13 @@ _cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
return info;
}
+void
+_cairo_xlib_screen_reset_static_data (void)
+{
+ _cairo_xlib_screen_info_reset ();
+
+#if HAVE_XRMFINALIZE
+ XrmFinalize ();
+#endif
+
+}
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 5f26a2f4..e4d52552 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1943,8 +1943,10 @@ _lock_xlib_glyphset_caches (void)
static void
_unlock_xlib_glyphset_caches (glyphset_cache_t *cache)
{
- _cairo_cache_shrink_to (&cache->base,
- CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT);
+ if (cache) {
+ _cairo_cache_shrink_to (&cache->base,
+ CAIRO_XLIB_GLYPH_CACHE_MEMORY_DEFAULT);
+ }
CAIRO_MUTEX_UNLOCK(_xlib_glyphset_caches_mutex);
}
@@ -2452,3 +2454,23 @@ _cairo_xlib_surface_show_glyphs (cairo_scaled_font_t *scaled_font,
return status;
}
+
+static void
+_destroy_glyphset_cache_recurse (glyphset_cache_t *cache)
+{
+ if (cache == NULL)
+ return;
+
+ _destroy_glyphset_cache_recurse (cache->next);
+ _cairo_cache_destroy (&cache->base);
+ free (cache);
+}
+
+void
+_cairo_xlib_surface_reset_static_data (void)
+{
+ _lock_xlib_glyphset_caches ();
+ _destroy_glyphset_cache_recurse (_xlib_glyphset_caches);
+ _xlib_glyphset_caches = NULL;
+ _unlock_xlib_glyphset_caches (NULL);
+}
diff --git a/src/cairo.h b/src/cairo.h
index ca4157a4..f43d9c58 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -38,14 +38,6 @@
#ifndef CAIRO_H
#define CAIRO_H
-#ifdef __cplusplus
-# define CAIRO_BEGIN_DECLS extern "C" {
-# define CAIRO_END_DECLS }
-#else
-# define CAIRO_BEGIN_DECLS
-# define CAIRO_END_DECLS
-#endif
-
#include <cairo-features.h>
CAIRO_BEGIN_DECLS
diff --git a/src/cairoint.h b/src/cairoint.h
index 74e70b94..794f3409 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -63,6 +63,7 @@
#include <stdio.h>
#include "cairo.h"
+#include "cairo-debug.h"
#include <pixman.h>
#if __GNUC__ >= 3 && defined(__ELF__)
@@ -518,6 +519,18 @@ _cairo_unlock_global_image_glyph_cache (void);
cairo_private cairo_cache_t *
_cairo_get_global_image_glyph_cache (void);
+cairo_private void
+_cairo_font_reset_static_data (void);
+
+cairo_private void
+_cairo_ft_font_reset_static_data (void);
+
+cairo_private void
+_cairo_xlib_surface_reset_static_data (void);
+
+cairo_private void
+_cairo_xlib_screen_reset_static_data (void);
+
/* Some glyph cache functions you can reuse. */
cairo_private unsigned long
diff --git a/test/cairo-test.c b/test/cairo-test.c
index 456d7d85..7e6d48de 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
+#include <fontconfig/fontconfig.h>
#include "cairo-test.h"
@@ -469,6 +470,9 @@ cairo_test_for_target (cairo_test_t *test,
UNWIND_CAIRO:
cairo_destroy (cr);
cairo_surface_destroy (surface);
+
+ cairo_debug_reset_static_data ();
+
target->cleanup_target (target->closure);
UNWIND_STRINGS:
@@ -557,6 +561,8 @@ cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw,
fclose (cairo_test_log_file);
+ FcFini ();
+
return ret;
}
diff --git a/test/cairo-test.h b/test/cairo-test.h
index beabc6a5..d35faab8 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -28,6 +28,7 @@
#include <math.h>
#include <cairo.h>
+#include <cairo-debug.h>
typedef enum cairo_test_status {
CAIRO_TEST_SUCCESS = 0,
diff --git a/test/xlib-surface.c b/test/xlib-surface.c
index 2921eb85..805ce18f 100644
--- a/test/xlib-surface.c
+++ b/test/xlib-surface.c
@@ -267,6 +267,8 @@ main (void)
XCloseDisplay (dpy);
+ cairo_debug_reset_static_data ();
+
fclose (log_file);
return result;