Opened 10 years ago

Closed 9 years ago

Last modified 9 years ago

#7666 closed Bugs (invalid)

Boost Thread SIGSEGV on join() when -D_GLIBCXX_DEBUG is used

Reported by: Antonio Di Monaco <tony@…> Owned by: viboes
Milestone: To Be Determined Component: thread
Version: Boost 1.52.0 Severity: Problem
Keywords: thread SIGSEGV C++11 -D_GLIBCXX_DEBUG Cc:

Description

I'd like to report a SIGSEGV using MinGW GCC 4.7.2 and Boost 1.52.0. Boost 1.51 is working fine.

I've compiled Boost libraries using "-std=c++11 -std=gnu++11" flags.

If I compile this code:

#include <boost/thread/thread.hpp>

void myFunc()
{
  boost::this_thread::sleep(boost::posix_time::seconds(5));
}

int main(int, char **)
{
  boost::thread p(myFunc);

  p.join();

  return 0;
}

with the following flags:

-DBOOST_ALL_DYN_LINK -DBOOST_ASIO_DISABLE_BUFFER_DEBUGGING -DBOOST_CHRONO_VERSION=2 -DBOOST_FILESYSTEM_NO_DEPRECATED -DBOOST_FILESYSTEM_VERSION=3 -DBOOST_THREAD_DONT_PROVIDE_DEPRECATED_FEATURES_SINCE_V3_0_0 -DBOOST_THREAD_VERSION=3 -DSIMULATOR -DUNICODE -D_UNICODE -D_WIN32_WINNT=0x0500 -std=c++11 -std=gnu++11 -mno-ms-bitfields -Wall -Wextra -Wuninitialized -Wold-style-cast -Woverloaded-virtual -Wnoexcept -Wnon-virtual-dtor -Winit-self -Wmissing-include-dirs -Wunused-parameter -pedantic -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -g -O0 -fno-inline -gdwarf-2 -g3 -fstack-protector-all

and I link it with the following options:

-lssp C:\MinGW\lib\libboost_system-mt-d.dll C:\MinGW\lib\libboost_thread-mt-d.dll C:\MinGW\lib\libboost_chrono-mt-d.dll -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32 

at run the thread is launched, and after 5 seconds I get a SIGSEGV, with the following GDB backtrace:

(gdb) r
Starting program: C:\Users\Tony\Documents\sitradesdk\output\atomictest.exe
[New Thread 1224.0xcb0]
[New Thread 1224.0xf10]

Program received signal SIGSEGV, Segmentation fault.
0x70a012cf in boost::detail::thread_data_base::~thread_data_base (
    this=0x8750d0, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:43
43                  i->second->unlock();
(gdb) bt
#0  0x70a012cf in boost::detail::thread_data_base::~thread_data_base (
    this=0x8750d0, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:43
#1  0x00405d9c in _fu832____stack_chk_guard ()
    at C:/MinGW/include/boost/thread/detail/thread.hpp:52
#2  0x70a0730a in boost::detail::heap_delete<boost::detail::thread_data_base>
    (data=0x8750d0) at ./boost/thread/win32/thread_heap_alloc.hpp:416
#3  0x70a08069 in boost::detail::intrusive_ptr_release (p=0x8750d0)
    at ./boost/thread/win32/thread_data.hpp:121
#4  0x70a0422b in boost::intrusive_ptr<boost::detail::thread_data_base>::~intrus
ive_ptr (this=0x28fe58, __in_chrg=<optimized out>)
    at ./boost/smart_ptr/intrusive_ptr.hpp:96
#5  0x70a01cc0 in boost::thread::join (this=0x28fef8)
    at libs\thread\src\win32\thread.cpp:331
#6  0x004015c1 in _fu12____stack_chk_guard ()
    at C:\Users\Tony\Documents\sitradesdk\test\utils\atomic.cpp:82

Change History (41)

comment:1 by anonymous, 10 years ago

I have tried the test after installing gcc-4.7.2. I don't reach to reproduce adding -fstack-protector-all and -lssp to my command line.

Please, could you try to reduce the compiler flags and the libraries you link with so that it is easy I reproduce it?

comment:2 by Antonio Di Monaco <tony@…>, 10 years ago

Maybe I've found it.

You just need to build the test code with _GLIBCXX_DEBUG.

This is now my gcc command lines (taken from CMake output):

/C/MinGW/bin/g++.exe -std=c++11 -std=gnu++11 -mno-ms-bitfields -Wall -Wextra -Wuninitialized -Wold-style-cast -Woverloaded-virtual -Wnoexcept -Wnon-virtual-dtor -Winit-self -Wmissing-include-dirs -Wunused-parameter -pedantic -D_GLIBCXX_DEBUG -g -O0 -fno-inline -gdwarf-2 -g3 @CMakeFiles/threadtest.dir/includes_CXX.rsp   -o CMakeFiles/threadtest.dir/thread.cpp.obj -c /c/Users/Tony/Documents/sitradesdk/test/utils/thread.cpp
/C/MinGW/bin/g++.exe -std=c++11 -std=gnu++11 -mno-ms-bitfields -Wall -Wextra -Wuninitialized -Wold-style-cast -Woverloaded-virtual -Wnoexcept -Wnon-virtual-dtor -Winit-self -Wmissing-include-dirs -Wunused-parameter -pedantic -D_GLIBCXX_DEBUG -g -O0 -fno-inline -gdwarf-2 -g3    -Wl,--whole-archive CMakeFiles/threadtest.dir/objects.a -Wl,--no-whole-archive  -o threadtest.exe -Wl,--out-implib,libthreadtest.dll.a -Wl,--major-image-version,0,--minor-image-version,0  /C/MinGW/lib/libboost_system-mt-d.dll /C/MinGW/lib/libboost_thread-mt-d.dll /C/MinGW/lib/libboost_chrono-mt-d.dll -lkernel32 -luser32 -lgdi32 -lwinspool -lshell32 -lole32 -loleaut32 -luuid -lcomdlg32 -ladvapi32

comment:3 by Antonio Di Monaco <tony@…>, 10 years ago

Moreover, you don't need to link with chrono library when compiling the test code. Just system and thread (mt-d variant).

comment:4 by viboes, 10 years ago

Summary: Boost Thread SIGSEGVBoost Thread SIGSEGV on join() when -fstack-protector-all

I have reached to reproduce the error. I will need sometime to take care of this issue.

comment:5 by anonymous, 10 years ago

Great. But you don't need to use stack protection feature. I was able to reproduce it just defining _GLIBCXX_DEBUG during compilation.

comment:6 by viboes, 9 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

comment:7 by anonymous, 9 years ago

Reproducible with _GLIBCXX_DEBUG on GCC 4.8.1; compiling natively on Fedora 19.

comment:8 by viboes, 9 years ago

See also #8788

comment:9 by viboes, 9 years ago

Keywords: -D_GLIBCXX_DEBUG added
Summary: Boost Thread SIGSEGV on join() when -fstack-protector-allBoost Thread SIGSEGV on join() when -D_GLIBCXX_DEBUG is used

comment:10 by viboes, 9 years ago

Please, could you try these patches in case it could be related to this issue.

svn diff win32/thread_data.hpp
Index: win32/thread_data.hpp
===================================================================
--- win32/thread_data.hpp	(revision 85663)
+++ win32/thread_data.hpp	(working copy)
@@ -148,7 +148,7 @@
 
             virtual void run()=0;
 
-            void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
+            virtual void notify_all_at_thread_exit(condition_variable* cv, mutex* m)
             {
               notify.push_back(std::pair<condition_variable*, mutex*>(cv, m));
             }

svn diff libs/thread/src/win32/thread.cpp 
Index: libs/thread/src/win32/thread.cpp
===================================================================
--- libs/thread/src/win32/thread.cpp	(revision 85677)
+++ libs/thread/src/win32/thread.cpp	(working copy)
@@ -279,6 +279,12 @@
                 interruption_enabled=false;
 #endif
             }
+            ~externally_launched_thread() {
+              BOOST_ASSERT(notify.empty());
+              notify.clear();
+              BOOST_ASSERT(async_states_.empty());
+              async_states_.clear();
+            }

Last edited 9 years ago by viboes (previous) (diff)

comment:11 by Antonio Di Monaco <tony@…>, 9 years ago

Unfortunately, the patch doesn't work. Tried with gcc 4.8.1 and boost-1.54.0, got same backtrace:

(gdb) r
Starting program: C:\Users\Tony\Downloads\boost_1_54_0\test.exe
[New Thread 3600.0xe14]
warning: SHIMVIEW: ShimInfo(Complete)

[New Thread 3600.0xa9c]

Program received signal SIGSEGV, Segmentation fault.
0x67e81537 in boost::detail::thread_data_base::~thread_data_base (
    this=0x5b23d0, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:45
45                  i->second->unlock();
(gdb) bt
#0  0x67e81537 in boost::detail::thread_data_base::~thread_data_base (
    this=0x5b23d0, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:45
#1  0x0040b4e8 in boost::detail::thread_data<void (*)()>::~thread_data (
    this=0x5b23d0, __in_chrg=<optimized out>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:91
#2  0x67e8f542 in boost::detail::heap_delete<boost::detail::thread_data_base>
    (data=0x5b23d0) at ./boost/thread/win32/thread_heap_alloc.hpp:391
#3  0x67e90971 in boost::detail::intrusive_ptr_release (p=0x5b23d0)
    at ./boost/thread/win32/thread_data.hpp:137
#4  0x67e8abef in boost::intrusive_ptr<boost::detail::thread_data_base>::~intrus
ive_ptr (this=0x28fd5c, __in_chrg=<optimized out>)
    at ./boost/smart_ptr/intrusive_ptr.hpp:97
#5  0x67e822b5 in boost::thread::join_noexcept (this=0x28fe8c)
    at libs\thread\src\win32\thread.cpp:354
#6  0x0040c183 in boost::thread::join (this=0x28fe8c)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:756
#7  0x00401734 in main () at test.cpp:12

comment:12 by viboes, 9 years ago

I don't understand how the error is in

45                  i->second->unlock();

after the patch. The patch ensure that there are no elements in notify and so the following code shouldn't crash.

    thread_data_base::~thread_data_base()
    {
        for (notify_list_t::iterator i = notify.begin(), e = notify.end();
                i != e; ++i)
        {
            i->second->unlock();
            i->first->notify_all();
        }
        for (async_states_t::iterator i = async_states_.begin(), e = async_states_.end();
                i != e; ++i)
        {
            (*i)->make_ready();
        }
    }

Please could you comment the code inside this function in src/win32/thread.cpp?

comment:13 by viboes, 9 years ago

Milestone: To Be DeterminedBoost 1.55.0

Committed revision [85734].

comment:14 by viboes, 9 years ago

See #8586, #9118.

Last edited 9 years ago by viboes (previous) (diff)

comment:15 by Antonio Di Monaco <tony@…>, 9 years ago

Commented all code inside thread_data_base::~thread_data_base(), test is fine, no SIGSEGV anymore.

in reply to:  15 comment:16 by viboes, 9 years ago

Replying to Antonio Di Monaco <tony@…>:

Commented all code inside thread_data_base::~thread_data_base(), test is fine, no SIGSEGV anymore.

Hrrr, I suspect that the thread data of the main thread is incoherent. Evidently this is not a solution just a patch..

I would need to reproduce the issue, but I don't reach to do it now.

If this is deterministic, could you use a debugger and stop at the beginning of ~thread_data_base() and inspect the notify variable?

Thanks your help.

comment:17 by Antonio Di Monaco <tony@…>, 9 years ago

Maybe there's something here. I applied the patch, I started with a full run, just to be sure that SIGSEGV was still present, and then I printed out notify variable.

(gdb) b boost::detail::thread_data_base::~thread_data_base()
Breakpoint 1 at 0x40188c
(gdb) r
Starting program: C:\Documents and Settings\dev\Documenti\Downloads\test.exe
[New Thread 2356.0xed0]
[New Thread 2356.0xf28]

Breakpoint 1, 0x0040188c in boost::detail::thread_data_base::~thread_data_base()
 ()
(gdb) c
Continuing.

Breakpoint 1, boost::detail::thread_data_base::~thread_data_base (
    this=0x243330, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:40
40          thread_data_base::~thread_data_base()
(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x67e81517 in boost::detail::thread_data_base::~thread_data_base (
    this=0x243330, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:45
45                  i->second->unlock();
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: C:\Documents and Settings\dev\Documenti\Downloads\test.exe
[New Thread 3604.0x834]
[New Thread 3604.0x58c]

Breakpoint 1, 0x0040188c in boost::detail::thread_data_base::~thread_data_base()
 ()
(gdb) s
Single stepping until exit from function _ZN5boost6detail16thread_data_baseD2Ev,
which has no line number information.
boost::detail::thread_data_base::~thread_data_base (
    this=0x6ced3354 <libgcc_s_sjlj-1!_Unwind_SjLj_Register+116>,
    __in_chrg=<optimized out>) at libs\thread\src\win32\thread.cpp:40
40          thread_data_base::~thread_data_base()
(gdb) s

Breakpoint 1, boost::detail::thread_data_base::~thread_data_base (
    this=0x243330, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:40
40          thread_data_base::~thread_data_base()
(gdb) s
42              for (notify_list_t::iterator i = notify.begin(), e = notify.end(
);
(gdb) p notify
$1 = std::vector of length 0, capacity 0 = {Cannot access memory at address 0x0
(gdb) p async_states_
$2 = std::vector of length 0, capacity 0

Seems that internal buffer of notify vector has been lost. Move operation somewhere??? (just guessing...)

in reply to:  17 comment:18 by viboes, 9 years ago

Replying to Antonio Di Monaco <tony@…>:

Maybe there's something here. I applied the patch, I started with a full run, just to be sure that SIGSEGV was still present, and then I printed out notify variable.

> Breakpoint 1, boost::detail::thread_data_base::~thread_data_base (
>     this=0x243330, __in_chrg=<optimized out>)
>     at libs\thread\src\win32\thread.cpp:40
> 40          thread_data_base::~thread_data_base()
> (gdb) s
> 42              for (notify_list_t::iterator i = notify.begin(), e = notify.end(
> );
> (gdb) p notify
> $1 = std::vector of length 0, capacity 0 = {Cannot access memory at address 0x0
> (gdb) p async_states_
> $2 = std::vector of length 0, capacity 0
> }}}

Could you try to see when the access to address 0x0 is done? Could you do a step on notify.begin()?

Seems that internal buffer of notify vector has been lost. Move operation somewhere??? (just guessing...)

I don't think so. This class is not moved.

Last edited 9 years ago by viboes (previous) (diff)

comment:19 by Antonio Di Monaco <tony@…>, 9 years ago

Ok. Seems that the access to 0x0 is just when " i-> " is performed.

Breakpoint 1, 0x0040188c in boost::detail::thread_data_base::~thread_data_base()
 ()
(gdb) s
Single stepping until exit from function _ZN5boost6detail16thread_data_baseD2Ev,

which has no line number information.
boost::detail::thread_data_base::~thread_data_base (
    this=0x6ced3354 <libgcc_s_sjlj-1!_Unwind_SjLj_Register+116>,
    __in_chrg=<optimized out>) at libs\thread\src\win32\thread.cpp:40
40          thread_data_base::~thread_data_base()
(gdb)

Breakpoint 1, boost::detail::thread_data_base::~thread_data_base (
    this=0x243330, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:40
40          thread_data_base::~thread_data_base()
(gdb)
42              for (notify_list_t::iterator i = notify.begin(), e = notify.end(
);
(gdb)
std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::allocator
<std::pair<boost::condition_variable*, boost::mutex*> > >::begin (
    this=0x24335c)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_vector.h:539
539           { return iterator(this->_M_impl._M_start); }
(gdb) p _M_impl
$3 = {<std::allocator<std::pair<boost::condition_variable*, boost::mutex*> >> =
{<__gnu_cxx::new_allocator<std::pair<boost::condition_variable*, boost::mutex*>
>> = {<No data fields>}, <No data fields>}, _M_start = 0x0,
  _M_finish = 0x1, _M_end_of_storage = 0x0}
(gdb) s
__gnu_cxx::__normal_iterator<std::pair<boost::condition_variable*, boost::mutex*
>*, std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::alloc
ator<std::pair<boost::condition_variable*, boost::mutex*> > > >::__normal_iterat
or (this=0x22fbec, __i=@0x24335c: 0x0)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_iterator.h:726
726           __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
(gdb)
std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::allocator
<std::pair<boost::condition_variable*, boost::mutex*> > >::end (
    this=0x24335c)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_vector.h:557
557           { return iterator(this->_M_impl._M_finish); }
(gdb)
__gnu_cxx::__normal_iterator<std::pair<boost::condition_variable*, boost::mutex*
>*, std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::alloc
ator<std::pair<boost::condition_variable*, boost::mutex*> > > >::__normal_iterat
or (this=0x22fbec, __i=@0x243360: 0x1)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_iterator.h:726
726           __normal_iterator(const _Iterator& __i) : _M_current(__i) { }
(gdb)
__gnu_cxx::operator!=<std::pair<boost::condition_variable*, boost::mutex*>*, std
::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::allocator<st
d::pair<boost::condition_variable*, boost::mutex*> > > > (
    __lhs=<error reading variable: Cannot access memory at address 0x0>,
    __rhs=<error reading variable: Cannot access memory at address 0x1>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_iterator.h:825
825         { return __lhs.base() != __rhs.base(); }
(gdb)
__gnu_cxx::__normal_iterator<std::pair<boost::condition_variable*, boost::mutex*
>*, std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::alloc
ator<std::pair<boost::condition_variable*, boost::mutex*> > > >::base (
    this=0x22fc5c)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_iterator.h:791
791           { return _M_current; }
(gdb)
__gnu_cxx::__normal_iterator<std::pair<boost::condition_variable*, boost::mutex*
>*, std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::alloc
ator<std::pair<boost::condition_variable*, boost::mutex*> > > >::base (
    this=0x22fc58)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_iterator.h:791
791           { return _M_current; }
(gdb)
boost::detail::thread_data_base::~thread_data_base (this=0x243330,
    __in_chrg=<optimized out>) at libs\thread\src\win32\thread.cpp:45
45                  i->second->unlock();
(gdb) s
__gnu_cxx::__normal_iterator<std::pair<boost::condition_variable*, boost::mutex*
>*, std::vector<std::pair<boost::condition_variable*, boost::mutex*>, std::alloc
ator<std::pair<boost::condition_variable*, boost::mutex*> > > >::operator->
    (this=0x22fc5c)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/
stl_iterator.h:743
743           { return _M_current; }
(gdb) p _M_current
$4 = (std::pair<boost::condition_variable*, boost::mutex*> *) 0x0
(gdb) s

Program received signal SIGSEGV, Segmentation fault.
0x67e81517 in boost::detail::thread_data_base::~thread_data_base (
    this=0x243330, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:45
45                  i->second->unlock();

comment:20 by viboes, 9 years ago

How is it thet notify.begin() doesn't return notify.end()? Could you step through it?

comment:21 by Antonio Di Monaco <tony@…>, 9 years ago

Well, I tried stepping, but it was not feasible for me.

Anyway, I tried to "watch" notify variable, and something weird happens even before the thread is created and launched:

Breakpoint 1 at 0x40b6bc: file C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp, line 123.
Starting program: C:\Users\Tony\Downloads\boost_1_54_0\test.exe 
[New Thread 3940.0xb20]

Breakpoint 1, boost::detail::thread_data_base::thread_data_base (
    this=0x7748d8)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp:123
123	                , interruption_enabled(true)
$1 = std::vector of length 0, capacity 0
Watchpoint 2: notify
$2 = std::vector of length 0, capacity 0
Continuing.
Watchpoint 2: notify

Old value = std::vector of length 0, capacity 0
New value = Cannot access memory at address 0x0
#0  0x00407e4c in __gnu_debug::_Safe_sequence_base::_Safe_sequence_base (
    this=0x774900)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_base.h:192
#1  0x00407db3 in __gnu_debug::_Safe_sequence<std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > > >::_Safe_sequence (
    this=0x774900)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_sequence.h:111
#2  0x00410754 in std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x7748e8, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/map.h:77
#3  0x0040b71b in _fu4___ZTVN5boost6detail16thread_data_baseE ()
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp:123
#4  0x0040b483 in boost::detail::thread_data<void (*)()>::thread_data(void (*&&)()) (this=0x7748d8, 
    f_=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x4f591>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:98
#5  0x0040bc75 in boost::detail::heap_new<boost::detail::thread_data<void (*)()>, void (*)()>(void (*&&)()) (
    a1=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x4f591>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_heap_alloc.hpp:100
#6  0x0040c0b5 in boost::thread::make_thread_info (f=0x401637 <myFunc()>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:220
#7  0x0040c229 in boost::thread::thread<void (&)()> (this=0x28fe8c, 
    f=@0x401637: {void (void)} 0x401637 <myFunc()>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:265
#8  0x00401720 in main () at test.cpp:10
Continuing.
Watchpoint 2: notify

Old value = Cannot access memory at address 0x0
Continuing.
Watchpoint 2: notify

Old value = Cannot access memory at address 0x0
Continuing.

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
0x779cdd84 in ?? ()
Continuing.
[New Thread 3940.0x700]

Program received signal SIGSEGV, Segmentation fault.
0x67e81537 in boost::detail::thread_data_base::~thread_data_base (
    this=0x7748d8, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:45
45	            i->second->unlock();
Continuing.

Program received signal SIGSEGV, Segmentation fault.
0x67e81537 in boost::detail::thread_data_base::~thread_data_base (
    this=0x7748d8, __in_chrg=<optimized out>)
    at libs\thread\src\win32\thread.cpp:45
45	            i->second->unlock();
A debugging session is active.

	Inferior 1 [process 3940] will be killed.

Constructor thread_data_base::thread_data_base is called for the first time, and notify variable seems in a clean state. Then, it breaks again there, and now seems corrupted or something similar. Only after 3 "continue" the thread is created, sleep, and join, and SIGSEGV triggers.

Can you provide some methods where I can set up breakpoints, and print "notify" values each time that they're triggered?

comment:22 by Antonio Di Monaco <tony@…>, 9 years ago

I also got stepping from "good" notify value to the first modification. Hope that it's useful.

Breakpoint 1 at 0x40b6bc: file C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp, line 123.
Starting program: C:\Users\Tony\Downloads\boost_1_54_0\test.exe 
[New Thread 968.0xa20]

Breakpoint 1, boost::detail::thread_data_base::thread_data_base (
    this=0x7b48d8)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp:123
123	                , interruption_enabled(true)
$1 = std::vector of length 0, capacity 0
$2 = (boost::detail::thread_data_base::notify_list_t *) 0x7b4904
Watchpoint 2: notify
boost::detail::win32::handle_manager::handle_manager (this=0x7b48e0, 
    handle_to_manage_=0xffffffff)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_primitives.hpp:281
281	                    handle_to_manage(handle_to_manage_)
282	                {}
std::allocator<std::pair<void const* const, boost::detail::tss_data_node> >::allocator (this=0x28fcdc)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:113
113	      allocator() throw() { }
__gnu_cxx::new_allocator<std::pair<void const* const, boost::detail::tss_data_node> >::new_allocator (this=0x28fcdc)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:79
79	      new_allocator() _GLIBCXX_USE_NOEXCEPT { }
std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x7b48e8, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/map.h:77
77	      : _Base(__comp, __a) { }
std::__cxx1998::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x7b48e8, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_map.h:171
171	      : _M_t(__comp, _Pair_alloc_type(__a)) { }
std::allocator<std::pair<void const* const, boost::detail::tss_data_node> >::allocator (this=0x28fc3f, __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:116
116	      : __allocator_base<_Tp>(__a) { }
__gnu_cxx::new_allocator<std::pair<void const* const, boost::detail::tss_data_node> >::new_allocator (this=0x28fc3f)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:81
81	      new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree (this=0x7b48e8, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:652
652	      : _M_impl(__comp, _Node_allocator(__a)) { }
std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::allocator<std::pair<void const* const, boost::detail::tss_data_node> > (this=0x28fbbf)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:119
119	        allocator(const allocator<_Tp1>&) throw() { }
__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::new_allocator (this=0x28fbbf)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:79
79	      new_allocator() _GLIBCXX_USE_NOEXCEPT { }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_Rb_tree_impl(std::less<void const*> const&, std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&&) (
    this=0x7b48e8, __comp=..., 
    __a=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x53da0>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:457
457		  : _Node_allocator(std::move(__a)), _M_key_compare(__comp),
std::move<std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&> (__t=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/move.h:102
102	    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_Rb_tree_impl(std::less<void const*> const&, std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&&) (
    this=0x7b48e8, __comp=..., 
    __a=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x53da0>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:458
458		    _M_header(), _M_node_count(0)
std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::allocator (this=0x7b48e8, __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:116
116	      : __allocator_base<_Tp>(__a) { }
__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::new_allocator (this=0x7b48e8)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:81
81	      new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_Rb_tree_impl(std::less<void const*> const&, std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&&) (
    this=0x7b48e8, __comp=..., 
    __a=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x53da0>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:459
459		  { _M_initialize(); }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_M_initialize (this=0x7b48e8)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:466
466		    this->_M_header._M_color = _S_red;
467		    this->_M_header._M_parent = 0;
468		    this->_M_header._M_left = &this->_M_header;
469		    this->_M_header._M_right = &this->_M_header;
470		  }	    
std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::~allocator (this=0x28fbbf, __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:121
121	      ~allocator() throw() { }
__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::~new_allocator (this=0x28fbbf, 
    __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:86
86	      ~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
std::allocator<std::pair<void const* const, boost::detail::tss_data_node> >::~allocator (this=0x28fc3f, __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:121
121	      ~allocator() throw() { }
__gnu_cxx::new_allocator<std::pair<void const* const, boost::detail::tss_data_node> >::~new_allocator (this=0x28fc3f, __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:86
86	      ~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
__gnu_debug::_Safe_sequence<std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > > >::_Safe_sequence (this=0x7b4900)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_sequence.h:111
111	    class _Safe_sequence : public _Safe_sequence_base
__gnu_debug::_Safe_sequence_base::_Safe_sequence_base (this=0x7b4900)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_base.h:192
192	    : _M_iterators(0), _M_const_iterators(0), _M_version(1)
Watchpoint 2: notify

Old value = std::vector of length 0, capacity 0
New value = Cannot access memory at address 0x0
A debugging session is active.

	Inferior 1 [process 968] will be killed.

comment:23 by viboes, 9 years ago

Could you dump the stack, just before notify is written?

comment:24 by viboes, 9 years ago

Please, could you send me the output of the example preprocessed?

I wonder if you are not linking and compiling with the same Boost library?

Shouldn't you build boost with _GLIBCXX_DEBUG defined?

What is the size of boost::detail::thread_data_base on your program?

And in a Boost.Thread test?

Last edited 9 years ago by viboes (previous) (diff)

comment:25 by Antonio Di Monaco <tony@…>, 9 years ago

Here is the backtrace just before the "step" that will trigger the watch. But I don't think you'll get more info than the previous one I've already posted.

If it's fine, I can setup a VPN for you, and you can connect to my PC and remotely debug the issue. Please contact me to the email address reported in the bug.

Breakpoint 1 at 0x40b6bc: file C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp, line 123.
Starting program: C:\Users\Tony\Downloads\boost_1_54_0\test.exe 
[New Thread 2620.0x4e0]

Breakpoint 1, boost::detail::thread_data_base::thread_data_base (
    this=0x5248a0)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp:123
123	                , interruption_enabled(true)
$1 = std::vector of length 0, capacity 0
Watchpoint 2: notify
boost::detail::win32::handle_manager::handle_manager (this=0x5248a8, 
    handle_to_manage_=0xffffffff)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_primitives.hpp:281
281	                    handle_to_manage(handle_to_manage_)
282	                {}
std::allocator<std::pair<void const* const, boost::detail::tss_data_node> >::allocator (this=0x28fcdc)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:113
113	      allocator() throw() { }
__gnu_cxx::new_allocator<std::pair<void const* const, boost::detail::tss_data_node> >::new_allocator (this=0x28fcdc)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:79
79	      new_allocator() _GLIBCXX_USE_NOEXCEPT { }
std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x5248b0, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/map.h:77
77	      : _Base(__comp, __a) { }
std::__cxx1998::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x5248b0, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_map.h:171
171	      : _M_t(__comp, _Pair_alloc_type(__a)) { }
std::allocator<std::pair<void const* const, boost::detail::tss_data_node> >::allocator (this=0x28fc3f, __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:116
116	      : __allocator_base<_Tp>(__a) { }
__gnu_cxx::new_allocator<std::pair<void const* const, boost::detail::tss_data_node> >::new_allocator (this=0x28fc3f)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:81
81	      new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree (this=0x5248b0, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:652
652	      : _M_impl(__comp, _Node_allocator(__a)) { }
std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::allocator<std::pair<void const* const, boost::detail::tss_data_node> > (this=0x28fbbf)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:119
119	        allocator(const allocator<_Tp1>&) throw() { }
__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::new_allocator (this=0x28fbbf)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:79
79	      new_allocator() _GLIBCXX_USE_NOEXCEPT { }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_Rb_tree_impl(std::less<void const*> const&, std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&&) (
    this=0x5248b0, __comp=..., 
    __a=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x53da0>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:457
457		  : _Node_allocator(std::move(__a)), _M_key_compare(__comp),
std::move<std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&> (__t=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/move.h:102
102	    { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_Rb_tree_impl(std::less<void const*> const&, std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&&) (
    this=0x5248b0, __comp=..., 
    __a=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x53da0>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:458
458		    _M_header(), _M_node_count(0)
std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::allocator (this=0x5248b0, __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:116
116	      : __allocator_base<_Tp>(__a) { }
__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::new_allocator (this=0x5248b0)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:81
81	      new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_Rb_tree_impl(std::less<void const*> const&, std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >&&) (
    this=0x5248b0, __comp=..., 
    __a=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x53da0>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:459
459		  { _M_initialize(); }
std::_Rb_tree<void const*, std::pair<void const* const, boost::detail::tss_data_node>, std::_Select1st<std::pair<void const* const, boost::detail::tss_data_node> >, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::_Rb_tree_impl<std::less<void const*>, true>::_M_initialize (this=0x5248b0)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/stl_tree.h:466
466		    this->_M_header._M_color = _S_red;
467		    this->_M_header._M_parent = 0;
468		    this->_M_header._M_left = &this->_M_header;
469		    this->_M_header._M_right = &this->_M_header;
470		  }	    
std::allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::~allocator (this=0x28fbbf, __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:121
121	      ~allocator() throw() { }
__gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<void const* const, boost::detail::tss_data_node> > >::~new_allocator (this=0x28fbbf, 
    __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:86
86	      ~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
std::allocator<std::pair<void const* const, boost::detail::tss_data_node> >::~allocator (this=0x28fc3f, __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/bits/allocator.h:121
121	      ~allocator() throw() { }
__gnu_cxx::new_allocator<std::pair<void const* const, boost::detail::tss_data_node> >::~new_allocator (this=0x28fc3f, __in_chrg=<optimized out>)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/ext/new_allocator.h:86
86	      ~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
__gnu_debug::_Safe_sequence<std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > > >::_Safe_sequence (this=0x5248c8)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_sequence.h:111
111	    class _Safe_sequence : public _Safe_sequence_base
__gnu_debug::_Safe_sequence_base::_Safe_sequence_base (this=0x5248c8)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_base.h:192
192	    : _M_iterators(0), _M_const_iterators(0), _M_version(1)
#0  __gnu_debug::_Safe_sequence_base::_Safe_sequence_base (this=0x5248c8)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_base.h:192
#1  0x00407db3 in __gnu_debug::_Safe_sequence<std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > > >::_Safe_sequence (
    this=0x5248c8)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_sequence.h:111
#2  0x00410754 in std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x5248b0, __comp=..., __a=...)
    at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/map.h:77
#3  0x0040b71b in _fu4___ZTVN5boost6detail16thread_data_baseE ()
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp:123
#4  0x0040b483 in boost::detail::thread_data<void (*)()>::thread_data(void (*&&)()) (this=0x5248a0, 
    f_=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x4f591>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:98
#5  0x0040bc75 in boost::detail::heap_new<boost::detail::thread_data<void (*)()>, void (*)()>(void (*&&)()) (
    a1=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x4f591>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_heap_alloc.hpp:100
#6  0x0040c0b5 in boost::thread::make_thread_info (f=0x401637 <myFunc()>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:220
#7  0x0040c229 in boost::thread::thread<void (&)()> (this=0x28fe8c, 
    f=@0x401637: {void (void)} 0x401637 <myFunc()>)
    at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:265
#8  0x00401720 in main () at test.cpp:10

/// here I perform the last "step" command

Watchpoint 2: notify

Old value = std::vector of length 0, capacity 0
New value = Cannot access memory at address 0x0

comment:26 by Antonio Di Monaco <tony@…>, 9 years ago

Sorry, my email is not visible here.

Anyway, I'm not using _GLIBCXX_DEBUG when compiling boost. These are my instructions:

bootstrap gcc

b2 --prefix=my_mingw_root_dir --layout=tagged --without-python --without-mpi --without-context boost.locale.icu=off boost.locale.iconv=on toolset=gcc variant=release link=shared threading=multi runtime-link=shared cxxflags="-std=c++11 -std=gnu++11" install

Of course, now I'm using debug variant, and I don't have any other boost version installed in my PC, so this is the only one that I can link with.

I've created a preprocessed output of my test, you can download it here: http://www.becrux.com/test.cpp.zip

About thread_data_size, I put a breakpoint at constructor, and "p sizeof(*this)" returns 76.

What do you mean about "Boost.Thread test"?

comment:27 by Antonio Di Monaco <tony@…>, 9 years ago

Moreover, I don't know if I need to use _GLIBCXX_DEBUG even when building Boost. What I can say is that I've never used it with version <= 1.51.0, and it always worked fine.

Maybe I've always been lucky :)

in reply to:  26 comment:28 by viboes, 9 years ago

Replying to Antonio Di Monaco <tony@…>:

Sorry, my email is not visible here.

Anyway, I'm not using _GLIBCXX_DEBUG when compiling boost. These are my instructions:

bootstrap gcc

b2 --prefix=my_mingw_root_dir --layout=tagged --without-python --without-mpi --without-context boost.locale.icu=off boost.locale.iconv=on toolset=gcc variant=release link=shared threading=multi runtime-link=shared cxxflags="-std=c++11 -std=gnu++11" install

Of course, now I'm using debug variant, and I don't have any other boost version installed in my PC, so this is the only one that I can link with.

I've created a preprocessed output of my test, you can download it here: http://www.becrux.com/test.cpp.zip

About thread_data_size, I put a breakpoint at constructor, and "p sizeof(*this)" returns 76.

What do you mean about "Boost.Thread test"?

I pretended you to go to libs/thread/test and do bjam, but I see that you have access. Anyway, my suspicion is that the size is different. Could you compile your application again without _GLIBCXX_DEBUG and see the sizeof boost::detail::thread_data_base.

in reply to:  25 comment:29 by viboes, 9 years ago

Replying to Antonio Di Monaco <tony@…>:

Here is the backtrace just before the "step" that will trigger the watch. But I don't think you'll get more info than the previous one I've already posted.

If it's fine, I can setup a VPN for you, and you can connect to my PC and remotely debug the issue. Please contact me to the email address reported in the bug.

> #0  __gnu_debug::_Safe_sequence_base::_Safe_sequence_base (this=0x5248c8)
>     at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_base.h:192
> #1  0x00407db3 in __gnu_debug::_Safe_sequence<std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > > >::_Safe_sequence (
>     this=0x5248c8)
>     at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/safe_sequence.h:111
> #2  0x00410754 in std::__debug::map<void const*, boost::detail::tss_data_node, std::less<void const*>, std::allocator<std::pair<void const* const, boost::detail::tss_data_node> > >::map (this=0x5248b0, __comp=..., __a=...)
>     at c:/x32-481-win32-sjlj-r2/lib/gcc/i686-w64-mingw32/4.8.1/include/c++/debug/map.h:77
> #3  0x0040b71b in _fu4___ZTVN5boost6detail16thread_data_baseE ()
>     at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_data.hpp:123
> #4  0x0040b483 in boost::detail::thread_data<void (*)()>::thread_data(void (*&&)()) (this=0x5248a0, 
>     f_=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x4f591>)
>     at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:98
> #5  0x0040bc75 in boost::detail::heap_new<boost::detail::thread_data<void (*)()>, void (*)()>(void (*&&)()) (
>     a1=<unknown type in C:\Users\Tony\Downloads\boost_1_54_0\test.exe, CU 0x0, DIE 0x4f591>)
>     at C:/x32-481-win32-sjlj-r2/include/boost/thread/win32/thread_heap_alloc.hpp:100
> #6  0x0040c0b5 in boost::thread::make_thread_info (f=0x401637 <myFunc()>)
>     at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:220
> #7  0x0040c229 in boost::thread::thread<void (&)()> (this=0x28fe8c, 
>     f=@0x401637: {void (void)} 0x401637 <myFunc()>)
>     at C:/x32-481-win32-sjlj-r2/include/boost/thread/detail/thread.hpp:265
> #8  0x00401720 in main () at test.cpp:10
> 
> /// here I perform the last "step" command
> 
> Watchpoint 2: notify
> 
> Old value = std::vector of length 0, capacity 0
> New value = Cannot access memory at address 0x0

This is confusing. Do you mean that the pb is now at the thread construction? I was expecting the backtrace of the second time notify is written.

in reply to:  27 comment:30 by viboes, 9 years ago

Replying to Antonio Di Monaco <tony@…>:

Moreover, I don't know if I need to use _GLIBCXX_DEBUG even when building Boost. What I can say is that I've never used it with version <= 1.51.0, and it always worked fine.

Maybe I've always been lucky :)

Are you sure you are compiling and linking with the same boost library? Sorry for the question, but I'm trying to cover all the possibilities. Note that I appreciate too much the time you are taking to try to trap this issue.

Could you show your commands to build your example (compile and link)?

where is the Boost library?

where are the includes?

Last edited 9 years ago by viboes (previous) (diff)

comment:31 by Antonio Di Monaco <tony@…>, 9 years ago

I think that it's better to recap all the thing we have until now.

I have a clean Windows environment (no other toolchains like MSVC are present).

I use MingwBuilds, gcc 4.8.1, sjli, win32 thread.

Everything is in one folder, C:\x32-481-win32-sjlj-r2, so boost is in include\boost, and libraries are in C:\x32-481-win32-sjlj-r2\lib.

Anytime you asked me to apply a patch, I removed the whole dir include\boost and all libboost*.* present in C:\x32-481-win32-sjlj-r2\lib, extracted the boost-1.54.0 sources, applied the patch and rebuilt everything with the two command reported above. So I'm sure that I'm compiling and linking only against one version of boost (and I also check for the date of files before building).

I compile and link my test with the following command line:

c++ -o test.exe -std=c++11 -std=gnu++11 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -g -O0 -fno-inline -g3 -I"C:\x32-481-win32-sjlj-r2\include" test.cpp -L"C:\x32-481-win32-sjlj-r2\lib" -lboost_system-mt-d -lboost_thread-mt-d

Until here, I don't have any doubt about the test environment I'm using.

When test.exe is available, I run it with gdb, disabling hardware watchpoints, setting a breakpoint on boost::detail::thread_data_base::thread_data_base(), and run.

When breakpoint triggers, notify variable seems fine, print command does not report any issue about its content.

Then I add a watch on notify, and I start stepping. While stepping (it seems that something else is going to be constructed, but I can't understand what), notify watch triggers.

Seems like a memory overrun.

Anyway, I'll repeat the test again without -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC ASAP.

My offer to let you connect to my VPN is still valid, just contact me at tony --@-- becrux -- dot -- com, and I'll try to setup a GCC environment where you can perform your tests.

comment:32 by viboes, 9 years ago

Milestone: Boost 1.55.0To Be Determined

comment:33 by Chris Kogelnik, 9 years ago

I'm also seeing a Seg Fault on OS X 10.8 and boost 1.54 (and earlier) when issuing a thread.join(). A large project was previously working correctly until XCode was upgraded from 4 to 5. Reduced the case and traced it back to a compiler setting:

-stdlib=libc++ causes the crash

-stdlib=libstdc++ works fine

The DEBUG flag had nothing to do with it in this case.

Hope this helps your debugging.

There is the example, thread.cpp:

#include <stdio.h>
#include <stdlib.h>
#include <boost/thread.hpp>
#include <time.h>
#include <unistd.h>

using namespace std;

int loop = 1;

void
t1() {
  while (loop) {
    sleep(1);
  }
  printf("exiting\n");
  fflush(stdout);
}

int
main() {

  boost::thread t1_thread;

  t1_thread = boost::thread(t1);
  loop = 0;
  t1_thread.join();
}

The Makefile:

OPT_FAIL = -stdlib=libc++
OPT_PASS = -stdlib=libstdc++

thread: thread.cpp Makefile
  g++ -o thread thread.cpp -lboost_system -lboost_thread $(OPT_FAIL)

And the stack trace:

#0  boost::shared_ptr<boost::detail::future_object_base>::operator-> () at /boost_1_54_0/boost/smart_ptr/shared_ptr.hpp:652
#1  0x00000001038788c0 in boost::detail::thread_data_base::~thread_data_base (this=0x7fddbb403aa0) at libs/thread/src/pthread/thread.cpp:47
#2  0x000000010384a235 in boost::detail::thread_data<void (*)()>::~thread_data ()
#3  0x00000001038493e5 in boost::detail::thread_data<void (*)()>::~thread_data ()
#4  0x0000000103849408 in boost::detail::thread_data<void (*)()>::~thread_data ()
#5  0x000000010384b62e in boost::checked_delete<boost::detail::thread_data<void (*)()> > ()
#6  0x000000010384b749 in boost::detail::sp_counted_impl_p<boost::detail::thread_data<void (*)()> >::dispose ()
#7  0x000000010387955d in boost::detail::atomic_exchange_and_add () at /boost_1_54_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:146
#8  0x000000010387955d in boost::detail::sp_counted_base::weak_release () at /boost_1_54_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:158
#9  0x000000010387955d in boost::detail::sp_counted_base::release () at sp_counted_base_gcc_x86.hpp:147
#10 0x000000010387955d in boost::detail::shared_count::~shared_count () at sp_counted_base_gcc_x86.hpp:371
#11 0x000000010387955d in boost::shared_ptr<boost::detail::thread_data_base>::~shared_ptr () at sp_counted_base_gcc_x86.hpp:370
#12 0x000000010387955d in boost::shared_ptr<boost::detail::thread_data_base>::~shared_ptr () at /boost_1_54_0/boost/smart_ptr/detail/sp_counted_base_gcc_x86.hpp:722
#13 0x000000010387955d in boost::thread::join_noexcept (this=<value temporarily unavailable, due to optimizations>) at sp_counted_base_gcc_x86.hpp:338
#14 0x0000000103847344 in boost::thread::join ()
#15 0x0000000103846688 in main ()
Last edited 9 years ago by viboes (previous) (diff)

comment:34 by Chris Kogelnik, 9 years ago

Please note in the example above, 'int loop = 1;' should be a global defined prior to t1(). Editing code in a Wiki is poor form ;-)

comment:35 by viboes, 9 years ago

Whith which library was built Boost, -stdlib=libc++ or -stdlib=libstdc++ when the problem appear?

in reply to:  35 ; comment:36 by Chris Kogelnik, 9 years ago

Hi, sorry, this problem was an ABI incompatibility; the properly built library wasn't getting picked up. When both application and boost are compiled with the same stdlib there are no issues.

Interestingly, the only problem encountered in the larger case, with the mixed library use, was on thread join (not saying others don't exist).

in reply to:  36 comment:37 by viboes, 9 years ago

Replying to Chris Kogelnik:

Hi, sorry, this problem was an ABI incompatibility; the properly built library wasn't getting picked up. When both application and boost are compiled with the same stdlib there are no issues.

Interestingly, the only problem encountered in the larger case, with the mixed library use, was on thread join (not saying others don't exist).

Glad to see that there is no issue on Boost. I suspect that the GLIB issues is also related to an ABI incompatibility.

comment:38 by viboes, 9 years ago

Resolution: invalid
Status: assignedclosed

I suspect that this is related to an ABI incompatibility.

comment:39 by Antonio Di Monaco <tony@…>, 9 years ago

So? I didn't mix anything, and I still have the issue. GCC bug or what?

On release notes, mingw 4.7.2 / 4.8.0 is reported as "tested", how can I use it with _GLIBCXX_DEBUG???

comment:40 by viboes, 9 years ago

Have you tried to build Boost with _GLIBCXX_DEBUG?

comment:41 by Antonio Di Monaco <tony@…>, 9 years ago

Yeah, confirmed. _GLIBCXX_DEBUG breaks ABI compatibility.

Compiling Boost with _GLIBCXX_DEBUG solves the issue. Sorry for the noise.

Note: See TracTickets for help on using tickets.