summaryrefslogtreecommitdiff
path: root/src/cairo-mutex-impl-private.h
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2022-05-27 21:36:31 +0930
committerAdrian Johnson <ajohnson@redneon.com>2022-05-28 06:34:55 +0930
commita8c1858cf2bb6efb35c0678d135fd522ece9e2a4 (patch)
treee7b37d5013b2918dac57bb1bacbae00eb82655c4 /src/cairo-mutex-impl-private.h
parent5dafd7411660f153219abceab64d5cc3be1c59a6 (diff)
downloadcairo-a8c1858cf2bb6efb35c0678d135fd522ece9e2a4.tar.gz
Fix deadlock in cairo-scaled-font.c
When cairo_scaled_glyph_page_cache needs to remove entries, cairo-cache calls _cairo_hash_table_random_entry() with the predicate _cairo_scaled_glyph_page_can_remove(). This function checks that the glyph_page scaled_font is not locked by testing scaled_font->cache_frozen. The scaled font is locked in the cache-cache destroy entry callback: _cairo_scaled_glyph_page_pluck(). There is a race condition here between testing scaled_font->cache_frozen and locking the font. Fix this by adding a new CAIRO_MUTEX_TRY_LOCK mutex operation, and using it to test and lock the scaled font in _cairo_scaled_glyph_page_can_remove(). Fixes the multithreaded case in #440
Diffstat (limited to 'src/cairo-mutex-impl-private.h')
-rw-r--r--src/cairo-mutex-impl-private.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/src/cairo-mutex-impl-private.h b/src/cairo-mutex-impl-private.h
index 9f208aaa9..a8599d47e 100644
--- a/src/cairo-mutex-impl-private.h
+++ b/src/cairo-mutex-impl-private.h
@@ -87,6 +87,9 @@
* No trailing semicolons are needed (in any macro you define here).
* You should be able to compile the following snippet:
*
+ * - #define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) to try locking the mutex object,
+ * returning TRUE if the lock is acquired, FALSE if the mutex could not be locked.
+ *
* <programlisting>
* cairo_mutex_impl_t _cairo_some_mutex;
*
@@ -163,6 +166,7 @@
# define CAIRO_MUTEX_IMPL_NO 1
# define CAIRO_MUTEX_IMPL_INITIALIZE() CAIRO_MUTEX_IMPL_NOOP
# define CAIRO_MUTEX_IMPL_LOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
+# define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) (CAIRO_MUTEX_IMPL_NOOP1(mutex), TRUE)
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) CAIRO_MUTEX_IMPL_NOOP1(mutex)
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER 0
@@ -190,6 +194,7 @@
# define CAIRO_MUTEX_IMPL_WIN32 1
# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
+# define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) TryEnterCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex))
@@ -208,6 +213,7 @@
# define CAIRO_MUTEX_IMPL_INIT(mutex) pthread_mutex_init (&(mutex), NULL)
#endif
# define CAIRO_MUTEX_IMPL_LOCK(mutex) pthread_mutex_lock (&(mutex))
+# define CAIRO_MUTEX_IMPL_TRY_LOCK(mutex) (pthread_mutex_trylock (&(mutex)) == 0)
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) pthread_mutex_unlock (&(mutex))
#if HAVE_LOCKDEP
# define CAIRO_MUTEX_IS_LOCKED(mutex) LOCKDEP_IS_LOCKED (&(mutex))