diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2018-04-24 15:27:16 +0200 |
---|---|---|
committer | Milian Wolff <mail@milianw.de> | 2018-05-04 23:13:26 +0200 |
commit | 2bb51aa4fd46a61c4702f05a5c93e811a5e112ef (patch) | |
tree | 410e93c2f7856d2307398066b48c8bbb44019596 | |
parent | fba2ae7b2c43d3e706849c8098930683cbd0e322 (diff) | |
download | libunwind-2bb51aa4fd46a61c4702f05a5c93e811a5e112ef.tar.gz |
Fix data race on cache hints in find_reg_state
This can be reproduced by using libunwind from multiple threads with
UNW_CACHE_GLOBAL cache policy, as e.g. happens by default or when
libunwind wasn't build with --enable-per-thread-cache.
The call to put_rs_cache unlocks the cache, but we used to access
data that needs to be guarded still. So move the call to put_rs_cache
down to protect the data properly. Fixes the following data race
reported by TSAN:
WARNING: ThreadSanitizer: data race (pid=16551)
Read of size 2 at 0x7f7dda69ed7a by thread T2:
#0 find_reg_state ../../src/dwarf/Gparser.c:939 (libunwind.so.
8+0x000000037254)
#1 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:958 (libunwind.so.
8+0x000000037543)
#2 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so.
8+0x000000021fdd)
#3 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so.
8+0x0000000246cc)
#4 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so.
8+0x000000024be7)
#5 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so.
8+0x000000025058)
#6 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so.
8+0x00000001a6e7)
Previous write of size 2 at 0x7f7dda69ed7a by thread T3:
#0 find_reg_state ../../src/dwarf/Gparser.c:940 (libunwind.so.
8+0x000000037383)
#1 _ULx86_64_dwarf_step ../../src/dwarf/Gparser.c:958 (libunwind.so.
8+0x000000037543)
#2 _ULx86_64_step ../../src/x86_64/Gstep.c:71 (libunwind.so.
8+0x000000021fdd)
#3 trace_init_addr ../../src/x86_64/Gtrace.c:248 (libunwind.so.
8+0x0000000246cc)
#4 trace_lookup ../../src/x86_64/Gtrace.c:330 (libunwind.so.
8+0x000000024be7)
#5 _ULx86_64_tdep_trace ../../src/x86_64/Gtrace.c:447 (libunwind.so.
8+0x000000025058)
#6 unw_backtrace ../../src/mi/backtrace.c:69 (libunwind.so.
8+0x00000001a6e7)
Location is global 'local_addr_space' of size 26296 at 0x7f7dda698c60
(libunwind.so.8+0x000000268d7a)
-rw-r--r-- | src/dwarf/Gparser.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/src/dwarf/Gparser.c b/src/dwarf/Gparser.c index 7ddd8ded..3f79ed4c 100644 --- a/src/dwarf/Gparser.c +++ b/src/dwarf/Gparser.c @@ -932,7 +932,6 @@ find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr) unsigned short index = -1; if (cache) { - put_rs_cache (c->as, cache, &saved_mask); if (rs) { index = rs - cache->buckets; @@ -940,6 +939,7 @@ find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr) cache->links[c->prev_rs].hint = index + 1; c->prev_rs = index; } + put_rs_cache (c->as, cache, &saved_mask); } if (ret < 0) return ret; |