-1

My legacy C++ codebase is failing in a multithreaded execution scenario when two threads are concurrently tries to allocate memory for STL vector. The stacktrace of two threads are given below.

-----------------  lwp# 4 / thread# 4  --------------------
 00136e10 allocate__t24__default_alloc_template2b0i0Ui (4, 4, 0, 0, 0, 0) + a4
 0015ee80 allocate__t12simple_alloc2ZP12ReconInitRecZt24__default_alloc_template2b0i0Ui (1, 0, 0, 0
, 0, 0) + 20
 0015da24 _M_allocate__t18_Vector_alloc_base3ZP12ReconInitRecZt9allocator1ZP12ReconInitRecb1Ui (86f
204, 1, 0, 0, 0, 0) + 10
 0014f438 _M_insert_aux__t6vector2ZP12ReconInitRecZt9allocator1ZP12ReconInitRecPP12ReconInitRecRCP1
2ReconInitRec (86f204, 0, fbe7fd04, 0, 0, 0) + cc
 0015f0a8 push_back__t6vector2ZP12ReconInitRecZt9allocator1ZP12ReconInitRecRCP12ReconInitRec (86f20
4, fbe7fd04, 0, 0, 0, 0) + 5c
 0015dbc0 push_back__t26ReconListOfRecFromMMapFile1ZP12ReconInitRecRCP12ReconInitRec (86f1f0, fbe7f
d04, 0, 0, fc551200, ff120400) + 28
 0017ca48 preprocess__8ReconCmpRCt26ReconListOfRecFromMMapFile1ZP12ReconInitRecb (86f160, 975100, 0
, b4, b4, 1) + 268
<<other stacktrace details truncated>>     
. . . .
 ff1494f0 _lwp_start (0, 0, 0, 0, 0, 0)
-----------------  lwp# 5 / thread# 5  --------------------
 ff14d1e4 _lwp_kill (6, 0, ff1b5010, ff12c928, ffffffff, 6) + 8
 ff0c1bac abort    (1f2b24, 1, 264ae4, ee930, ff1b34d8, 0) + 110
 001f2ca8 corehandler__7CdrSigsi (a, 0, fbaff4a8, 1, fedb2c40, cb4) + 184
 ff14961c __sighndlr (a, 0, fbaff4a8, 1f2b24, 0, 1) + c
 ff13dce8 call_user_handler (a, 0, 4, 0, fc551a00, fbaff4a8) + 3b8
 ff13ded0 sigacthandler (a, 0, fbaff4a8, 0, 0, 0) + 60
 --- called from signal handler with signal 10 (SIGBUS) ---
 00136e10 allocate__t24__default_alloc_template2b0i0Ui (8, 8, fbaffa38, 2d, 0, 0) + a4
 00126300 allocate__t12simple_alloc2Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc
_template2b0i0Zt24__default_alloc_template2b0i0Ui (2, 4, ffffffff, fbaffa38, 2d, 80808080) + 20
 00126338 _M_allocate__t18_Vector_alloc_base3Zt12basic_string3ZcZt18string_char_traits1ZcZt24__defa
ult_alloc_template2b0i0Zt9allocator1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc
_template2b0i0b1Ui (86f2a0, 2, 2d, fbaffa65, fbaffa65, 1) + 10
 00133768 _M_insert_aux__t6vector2Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_t
emplate2b0i0Zt9allocator1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b
0i0Pt12basic_string3ZcZt18string_char_traits1ZcZt24__defa (86f2a0, 8730b4, fbaffa20, fcbf4062, fbaf
fa65, 7fffffd2) + fc
 00157808 push_back__t6vector2Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_templ
ate2b0i0Zt9allocator1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0R
Ct12basic_string3ZcZt18string_char_traits1ZcZt24__default (86f2a0, fbaffa20, 7ffffc00, fcbf4062, 1c
, 2d) + 5c
 002064b8 getFiles__7ListDirb (86f280, 0, 253800, 4, 1c00, 1d3c) + 12c
<<other stacktrace details truncated>>     
. . . .

From the stacktrace, it shows that concurrent call to allocate__t24__default_alloc_template2b0i0Ui i.e. __default_alloc_template<false, 0>::allocate(unsigned int) is failing as this is not thread-safe. This allocate function is being called by the function

simple_alloc<X, __default_alloc_template<false, 0> >::allocate(unsi
gned int)

that in turn is called by

_Vector_alloc_base<X, allocator<X>, true>::_M_allocate
(unsigned int)

I would like to override one of these three functions, fpr overriding C++ STL allocator function to wrap it as threadsafe protected under mutual exclusion guarantee. Please advise.

Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • 4
    usually malloc/new are thread safe. (there might be exceptions to the rule in small embedded systems) please check if you use your containers in a thread-safe way – Alexander Nov 16 '17 at 08:50
  • BTW do you access the same vector from both threads? – Alexander Nov 16 '17 at 08:56
  • 4
    You have a concurrency bug. No amount of allocator workarounds is going to fix it. – molbdnilo Nov 16 '17 at 08:59
  • Looks like concurrency issue but the irritating the SIGBUS (https://stackoverflow.com/a/2090143/8918119). Both threads have no much in common except using ´std::vector::push_back()´ but have different type. Allocators are safe. – Mihayl Nov 16 '17 at 09:13
  • And also the problem could have been caused by other thread that changed the `vector::basic_string` (ListDir) at the same time the *thread# 5* was also modifying/reallocating it. – Mihayl Nov 16 '17 at 09:23

1 Answers1

2

You should synchronize your access to the containers instead of making the containers thread safe! It will end up in a nightmare if you try to reinvent the wheel. There is not only the insert and remove operations, but also element copy and shifting and also the concurrent operation on the stored elements.

In fact, I believe your design is broken and the container allocators only show that your application has design flaws.

BTW: Maybe you can use already implemented thread safe containers, instead of reinventing the wheel:

http://libcds.sourceforge.net/

http://www.boost.org/doc/libs/1_55_0/doc/html/lockfree.html

Remark: I never used them and can not say anything about robustness or other quality issues.

Klaus
  • 24,205
  • 7
  • 58
  • 113