From: David W. <dw...@in...> - 2010-09-25 08:57:53
|
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 |