[Freeassociation-devel] [PATCH] Fix race in populating builtin timezone components

David Woodhouse dwmw2 at infradead.org
Sat Sep 25 01:21:56 PDT 2010


When multiple threads call icaltimezone_get_component() for the same zone,
it can be populated by icaltimezone_load_builtin_timezone() multiple times
simultaneously, and bad things happen.

See GNOME bug https://bugzilla.gnome.org/show_bug.cgi?id=628139
---

I've also started mirroring libical from its current legacy version
control system into something more appropriate for the 21st century: 

  http://git.infradead.org/libical.git
   git://git.infradead.org/libical.git

This should be automatically updated.

 libical/src/libical/icaltimezone.c |   31 ++++++++++++++++++++-----------
 1 files changed, 20 insertions(+), 11 deletions(-)

diff --git a/libical/src/libical/icaltimezone.c b/libical/src/libical/icaltimezone.c
index 1b39f5f..101de21 100644
--- a/libical/src/libical/icaltimezone.c
+++ b/libical/src/libical/icaltimezone.c
@@ -45,6 +45,11 @@
 
 #include <sys/stat.h>
 
+#ifdef HAVE_PTHREAD
+#include <pthread.h>
+static pthread_mutex_t builtin_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
 #ifdef WIN32
 #include <mbstring.h>
 #include <windows.h>
@@ -453,8 +458,7 @@ icaltimezone_ensure_coverage		(icaltimezone *zone,
 
     int changes_end_year;
 
-    if (!zone->component)
-	icaltimezone_load_builtin_timezone (zone);
+    icaltimezone_load_builtin_timezone (zone);
 
     if (icaltimezone_minimum_expansion_year == -1) {
 	struct icaltimetype today = icaltime_today();
@@ -1140,8 +1144,7 @@ icaltimezone_get_tzid			(icaltimezone *zone)
     if (!zone)
 	return NULL;
 
-    if (!zone->tzid)
-	icaltimezone_load_builtin_timezone (zone);
+    icaltimezone_load_builtin_timezone (zone);
 
     return zone->tzid;
 }
@@ -1167,8 +1170,7 @@ icaltimezone_get_tznames		(icaltimezone *zone)
     if (!zone)
 	return NULL;
 
-    if (!zone->component)
-	icaltimezone_load_builtin_timezone (zone);
+    icaltimezone_load_builtin_timezone (zone);
 
     return zone->tznames;
 }
@@ -1210,8 +1212,7 @@ icaltimezone_get_component		(icaltimezone *zone)
     if (!zone)
 	return NULL;
 
-    if (!zone->component)
-	icaltimezone_load_builtin_timezone (zone);
+    icaltimezone_load_builtin_timezone (zone);
 
     return zone->component;
 }
@@ -1449,8 +1450,7 @@ icaltimezone_get_builtin_timezone_from_offset	(int offset, const char *tzname)
     for (i=0; i<count; i++) {
 	int z_offset;
 	zone = icalarray_element_at (builtin_timezones, i);
-	if (!zone->component)
-	    icaltimezone_load_builtin_timezone (zone);
+	icaltimezone_load_builtin_timezone (zone);
 	
 	z_offset = get_offset(zone);
 
@@ -1745,6 +1745,12 @@ icaltimezone_load_builtin_timezone	(icaltimezone *zone)
     if (!zone->location || !zone->location[0])
 	return;
 
+#ifdef HAVE_PTHREAD
+    pthread_mutex_lock(&builtin_mutex);
+    if (zone->component)
+	goto out;
+#endif
+
 #ifdef USE_BUILTIN_TZDATA
     {
     char *filename;
@@ -1802,7 +1808,10 @@ icaltimezone_load_builtin_timezone	(icaltimezone *zone)
     icalcomponent_free(comp);
     }
 #endif    
-
+#ifdef HAVE_PTHREAD
+ out:
+    pthread_mutex_unlock(&builtin_mutex);
+#endif
 }
 

-- 
1.7.2.2







More information about the libical-devel mailing list