diff options
Diffstat (limited to 'source/l/glibc/glibc-2.15.nscd-race-fix.diff')
-rw-r--r-- | source/l/glibc/glibc-2.15.nscd-race-fix.diff | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/source/l/glibc/glibc-2.15.nscd-race-fix.diff b/source/l/glibc/glibc-2.15.nscd-race-fix.diff new file mode 100644 index 00000000..f1323570 --- /dev/null +++ b/source/l/glibc/glibc-2.15.nscd-race-fix.diff @@ -0,0 +1,47 @@ +--- c/nscd/nscd_gethst_r.c 2012-01-01 05:16:32.000000000 -0700 ++++ c/nscd/nscd_gethst_r.c 2012-03-28 10:45:51.546600822 -0600 +@@ -101,9 +101,27 @@ libc_freeres_fn (hst_map_free) + uint32_t + __nscd_get_nl_timestamp (void) + { ++ uint32_t retval; + if (__nss_not_use_nscd_hosts != 0) + return 0; + ++ int cnt = 0; ++ /* __nscd_get_mapping can change hst_map_handle.mapped to NO_MAPPING. ++ However, __nscd_get_mapping assumes the prior value was not NO_MAPPING. ++ Thus we have to acquire the lock to prevent this thread from changing ++ hst_map_handle.mapped to NO_MAPPING while another thread is inside ++ __nscd_get_mapping. */ ++ while (__builtin_expect ++ (atomic_compare_and_exchange_val_acq (&__hst_map_handle.lock, ++ 1, 0) != 0, 0)) ++ { ++ // XXX Best number of rounds? ++ if (__builtin_expect (++cnt > 5, 0)) ++ return 0; ++ ++ atomic_delay (); ++ } ++ + struct mapped_database *map = __hst_map_handle.mapped; + + if (map == NULL +@@ -113,9 +131,14 @@ __nscd_get_nl_timestamp (void) + map = __nscd_get_mapping (GETFDHST, "hosts", &__hst_map_handle.mapped); + + if (map == NO_MAPPING) +- return 0; ++ retval = 0; ++ else ++ retval = map->head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]; ++ ++ /* Release the lock. */ ++ __hst_map_handle.lock = 0; + +- return map->head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]; ++ return retval; + } + + |