[Thread] Interrupting a thread causes a segmentation fault

Hello, I'm new to the Boost libraries and I've been attempting to implement basic multithreading using the Boost Thread library. I'm currently experiencing a problem: when I interrupt a thread my program crashes with a segmentation fault. I've done quite a bit of research on the internet regarding this problem and, although similar problems have been reported before, none of the solutions have worked for me (a number of people have indicated that interrupts work when linking with the static library, just not with the dynamic library, but I was using the static library to begin with). Technical details are: Boost version: 1.45.0 Compiler: MinGW 4.4.1 IDE: Code Blocks 10.05 The build log output from Code Blocks is: mingw32-g++.exe -Wall -fexceptions -g -I"C:\Program Files\boost\boost_1_45_0" -c "C:\Documents and Settings\WFrane\My Documents\C++ code\boost thread interrupt test\boost_thread_interrupt_test\main.cpp" -o obj\Debug\main.o mingw32-g++.exe -L"C:\Program Files\boost\boost_1_45_0\stage\lib" -o bin\Debug\boost_thread_interrupt_test.exe obj\Debug\main.o "C:\Program Files\boost\boost_1_45_0\stage\lib\libboost_thread-mgw44-mt-d-1_45.a" (I've also tried a release build with the appropriate version of the Boost.Thread library and the resulting program experiences the same problem.) I've included a short program below that exhibits this problem. Any suggestions as to what might be causing this and how it could be resolved would be appreciated. Regards, W. Frane EXAMPLE CODE: #define BOOST_THREAD_USE_LIB // This line was necessary to link with the static libraries. #include #include using namespace std; boost::mutex mutexCout; void testingThread(){ try{ while(1){ boost::this_thread::interruption_point(); } } catch(boost::thread_interrupted const& e){ // Thread was interrupted. mutexCout.lock(); cout << "THREAD: Ending." << endl; mutexCout.unlock(); } catch(...){ mutexCout.lock(); cout << "THREAD: Unknown exception." << endl; mutexCout.unlock(); } } int main(int argc, char* argv[]) { boost::thread testThread(testingThread); mutexCout.lock(); cout << "MAIN: Created thread; sleeping now." << endl; mutexCout.unlock(); boost::this_thread::sleep(boost::posix_time::seconds(4)); mutexCout.lock(); cout << "MAIN: About to interrupt thread." << endl; mutexCout.unlock(); testThread.interrupt(); // Segmentation fault occurs around here during program execution. mutexCout.lock(); cout << "MAIN: Sent interrupt to thread." << endl; mutexCout.unlock(); testThread.join(); cout << "MAIN: Thread has ended." << endl; return 0; }

I'm new to the Boost libraries and I've been attempting to implement basic multithreading using the Boost Thread library. I'm currently experiencing a problem: when I interrupt a thread my program crashes with a segmentation fault. I've done quite a bit of research on the internet regarding this problem and, although similar problems have been reported before, none of the solutions have worked for me (a number of people have indicated that interrupts work when linking with the static library, just not with the dynamic library, but I was using the static library to begin with).
Technical details are: Boost version: 1.45.0 Compiler: MinGW 4.4.1 IDE: Code Blocks 10.05
I believe the test programm is all right, it works well with boost 1.36 and 1.45 on linux with gcc 4.3.2 with both dynamic and static boost linkage. Check out the stack trace at the moment of failure, it shall give good insight into kind of problem. -- Slava

From: Viatcheslav.Sysoltsev@h-d-gmbh.de Date: Thu, 17 Feb 2011 09:42:53 +0100 Subject: Re: [Boost-users] [Thread] Interrupting a thread causes a segmentation fault
I believe the test programm is all right, it works well with boost 1.36 and 1.45 on linux with gcc 4.3.2 with both dynamic and static boost linkage. Check out the stack trace at the moment of failure, it shall give good insight into kind of problem.
-- Slava
I ran the debugger and took a look at the output at the point of the fault. Unfortunately, I didn't find it particularly enlightening, although it seems clear that the fault is occurring when the thread_interrupted exception is thrown by the Boost Thread library. In case it might be useful, I've included the information from the debugger below, as well as an excerpt from thread.cpp containing the function in which the fault occurs (to save anyone reading this the time of going to check the source). Any suggestions as to what might be the problem here would be appreciated; I also should note that I'm using Windows XP, so it may be an issue with the Windows API since the program apparently runs fine on Linux. Thanks, William CALL STACK ============================================================================= #0 00000000 0x00406410 in __cxa_throw() (??:??) #1 00403070 boost::this_thread::interruption_point() (libs\thread\src\win32\thread.cpp:495) #2 00401359 testingThread() (C:\Documents and Settings\WFrane\My Documents\C++ code\boost thread interrupt test\boost_thread_interrupt_test\main.cpp:12) #3 00422666 boost::detail::thread_data<void (*)() (C:/Program Files/boost/boost_1_45_0/boost/thread/detail/thread.hpp:61) #4 00401BFF thread_start_function(param=0x243198) (libs\thread\src\win32\thread.cpp:171) #5 77C3A3B0 msvcrt!_endthreadex() (C:\WINDOWS\system32\msvcrt.dll:??) #6 7C80B729 KERNEL32!GetModuleFileNameA() (C:\WINDOWS\system32\kernel32.dll:??) #7 00000000 0x00000000 in ??() (??:??) ============================================================================= CURRENT STACK FRAME ============================================================================= Stack level 1, frame at 0x78fe68: eip = 0x403070 in boost::this_thread::interruption_point() (libs\thread\src\win32\thread.cpp:495); saved eip 0x401359 called by frame at 0x78fef8, caller of frame at 0x78fe48 source language c++. Arglist at 0x78fe60, args: Locals at 0x78fe60, Previous frame's sp is 0x78fe68 Saved registers: ebp at 0x78fe60, eip at 0x78fe64 ============================================================================= DISASSEMBLY ============================================================================= Frame function: boost::this_thread::interruption_point() (libs\thread\src\win32\thread.cpp:495) Frame address : 0078FE68 -------------------------------------------------------------------------------- 0040300D push %ebp 0040300E mov %esp,%ebp 00403010 sub $0x18,%esp 00403013 call 0x403072 <boost::this_thread::interruption_enabled()> 00403018 test %al,%al 0040301A je 0x403029 <boost::this_thread::interruption_point()+28> 0040301C call 0x403095 <boost::this_thread::interruption_requested()> 00403021 test %al,%al 00403023 je 0x403029 <boost::this_thread::interruption_point()+28> 00403025 mov $0x1,%al 00403027 jmp 0x40302b <boost::this_thread::interruption_point()+30> 00403029 mov $0x0,%al 0040302B test %al,%al 0040302D je 0x403070 <boost::this_thread::interruption_point()+99> 0040302F call 0x40184c <get_current_thread_data> 00403034 add $0xc,%eax 00403037 mov %eax,(%esp) 0040303A call 0x4280dc <boost::detail::win32::handle_manager::operator void*() const> 0040303F mov %eax,(%esp) 00403042 mov 0x488298,%eax 00403047 call *%eax 00403049 sub $0x4,%esp 0040304C movl $0x1,(%esp) 00403053 call 0x405e8c <__cxa_allocate_exception> 00403058 movl $0x0,0x8(%esp) 00403060 movl $0x47ccec,0x4(%esp) 00403068 mov %eax,(%esp) 0040306B call 0x40640c <__cxa_throw> 00403070 leave 00403071 ret ============================================================================= SOURCE FOR boost::this_thread::interruption_point() (lines 490-497 of boost\boost_1_45_0\libs\thread\src\win32\thread.cpp) ============================================================================= void interruption_point() { if(interruption_enabled() && interruption_requested()) { detail::win32::ResetEvent(get_current_thread_data()->interruption_handle); throw thread_interrupted(); } } =============================================================================

On Thu, 17 Feb 2011 17:32:47 +0100, W Frane <molluskadvertising@hotmail.com> wrote:
CALL STACK ============================================================================= #0 00000000 0x00406410 in __cxa_throw() (??:??) #1 00403070 boost::this_thread::interruption_point() (libs\thread\src\win32\thread.cpp:495) #2 00401359 testingThread() (C:\Documents and Settings\WFrane\My Documents\C++ code\boost thread interrupt test\boost_thread_interrupt_test\main.cpp:12) #3 00422666 boost::detail::thread_data<void (*)() (C:/Program Files/boost/boost_1_45_0/boost/thread/detail/thread.hpp:61) #4 00401BFF thread_start_function(param=0x243198) (libs\thread\src\win32\thread.cpp:171) #5 77C3A3B0 msvcrt!_endthreadex() (C:\WINDOWS\system32\msvcrt.dll:??) #6 7C80B729 KERNEL32!GetModuleFileNameA() (C:\WINDOWS\system32\kernel32.dll:??) #7 00000000 0x00000000 in ??() (??:??) =============================================================================
CURRENT STACK FRAME ============================================================================= Stack level 1, frame at 0x78fe68: eip = 0x403070 in boost::this_thread::interruption_point() (libs\thread\src\win32\thread.cpp:495); saved eip 0x401359 called by frame at 0x78fef8, caller of frame at 0x78fe48 source language c++. Arglist at 0x78fe60, args: Locals at 0x78fe60, Previous frame's sp is 0x78fe68 Saved registers: ebp at 0x78fe60, eip at 0x78fe64 =============================================================================
DISASSEMBLY ============================================================================= Frame function: boost::this_thread::interruption_point() (libs\thread\src\win32\thread.cpp:495) Frame address : 0078FE68 -------------------------------------------------------------------------------- 0040300D push %ebp 0040300E mov %esp,%ebp 00403010 sub $0x18,%esp 00403013 call 0x403072 <boost::this_thread::interruption_enabled()> 00403018 test %al,%al 0040301A je 0x403029 <boost::this_thread::interruption_point()+28> 0040301C call 0x403095 <boost::this_thread::interruption_requested()> 00403021 test %al,%al 00403023 je 0x403029 <boost::this_thread::interruption_point()+28> 00403025 mov $0x1,%al 00403027 jmp 0x40302b <boost::this_thread::interruption_point()+30> 00403029 mov $0x0,%al 0040302B test %al,%al 0040302D je 0x403070 <boost::this_thread::interruption_point()+99> 0040302F call 0x40184c <get_current_thread_data> 00403034 add $0xc,%eax 00403037 mov %eax,(%esp) 0040303A call 0x4280dc <boost::detail::win32::handle_manager::operator void*() const> 0040303F mov %eax,(%esp) 00403042 mov 0x488298,%eax 00403047 call *%eax 00403049 sub $0x4,%esp 0040304C movl $0x1,(%esp) 00403053 call 0x405e8c <__cxa_allocate_exception> 00403058 movl $0x0,0x8(%esp) 00403060 movl $0x47ccec,0x4(%esp) 00403068 mov %eax,(%esp) 0040306B call 0x40640c <__cxa_throw> 00403070 leave 00403071 ret
Are you sure your compiler supports exception handling in your setup? I'd try some simple exception hanlding program with the same compiler switches. If you set breakpoint on 0040306B, does __cxa_throw resolve to 00000000 or you get there from inside __cxa_throw? If first, there something wrong with linking or compiler setup; if latter, something wrong with EH structures in generated code (either in boost or in your test program). Have you build boost yourelf? If not, maybe it is worthy to try to rebuild boost with the same compiler and try it. Make sure -fexceptions or whatevers it must be for mingw is used in build process. -- Slava

Are you sure your compiler supports exception handling in your setup? I'd try some simple exception hanlding program with the same compiler switches. If you set breakpoint on 0040306B, does __cxa_throw resolve to 00000000 or you get there from inside __cxa_throw? If first, there something wrong with linking or compiler setup; if latter, something wrong with EH structures in generated code (either in boost or in your test program). Have you build boost yourelf? If not, maybe it is worthy to try to rebuild boost with the same compiler and try it. Make sure -fexceptions or whatevers it must be for mingw is used in build process.
-- Slava
I've been compiling my test program with -fexceptions but I didn't originally compile the Boost libraries with that option. In light of this discussion, I recompiled the Boost libraries with -fexceptions (using the command .\bjam toolset=gcc cxxflags="-fexceptions" -a) and recompiled my test program. Unfortunately, the problem still persists. I added a breakpoint to 00403077 (after I recompiled my program after recompiling the Boost libraries as described above, 00403077 corresponded to the same line in the disassembly of boost::this_thread::interruption_point that 0040306B originally did) and it resolved to 0x2063f. I also added a breakpoint to __cxa_throw (in a separate debugging session) and it resolved to 0x40641c. In this second case (with the breakpoint at __cxa_throw), I stepped forward instruction by instruction once the breakpoint was reached and established that the segmentation fault occurs several instructions into __cxa_throw itself. I also ran a quick test program (modified from the test program I included in my original post) to check that the exception handling in MinGW is working. I altered the code so that the interrupt is removed and a std::exception is thrown by the thread function after 10 iterations of the while loop. The std::exception was caught without incident by the catch(...) block, so exception handling seems to work fine with regular exceptions. William

I've been compiling my test program with -fexceptions but I didn't originally compile the Boost libraries with that option. In light of this discussion, I recompiled the Boost libraries with -fexceptions (using the command .\bjam toolset=gcc cxxflags="-fexceptions" -a) and recompiled my test program. Unfortunately, the problem still persists.
I added a breakpoint to 00403077 (after I recompiled my program after recompiling the Boost libraries as described above, 00403077 corresponded to the same line in the disassembly of boost::this_thread::interruption_point that 0040306B originally did) and it resolved to 0x2063f. I also added a breakpoint to __cxa_throw (in a separate debugging session) and it resolved to 0x40641c. In this second case (with the breakpoint at __cxa_throw), I stepped forward instruction by instruction once the breakpoint was reached and established that the segmentation fault occurs several instructions into __cxa_throw itself.
I also ran a quick test program (modified from the test program I included in my original post) to check that the exception handling in MinGW is working. I altered the code so that the interrupt is removed and a std::exception is thrown by the thread function after 10 iterations of the while loop. The std::exception was caught without incident by the catch(...) block, so exception handling seems to work fine with regular exceptions.
Hi William, Maybe exception handling does not work well across dll boundary? I never used minGW, but internet search showed there were/are some difficulties with it. Is it feasible to upgrade to 4.5 compiler, since Andy says it works for him? -- Slava

Maybe exception handling does not work well across dll boundary? I never used minGW, but internet search showed there were/are some difficulties with it. Is it feasible to upgrade to 4.5 compiler, since Andy says it works for him?
-- Slava
Hello Slava, I'm linking all the Boost libraries statically, so I don't think DLL issues are the cause in this case (although I too have seen reports of Boost Thread functionality not working correctly when dynamically linking using MinGW). I'll upgrade MinGW and see if that resolves the issue. Regards, William

On 2/22/2011 8:16 AM, W Frane wrote:
I'm linking all the Boost libraries statically
Are you sure you're not getting more than one boost library in your executable then? I've managed to do that before (with MSVC, not MinGW), and those bugs can be a PITA to find.

Are you sure you're not getting more than one boost library in your executable then?
I've managed to do that before (with MSVC, not MinGW), and those bugs can be a PITA to find.
Do you mean more than one version of the same library, e.g., debug and release? If so, I'm fairly certain that's not happening (the build commands used are in my first post, and only one version of the Boost Thread library is linked). However, if I've misunderstood you, please let me know; I did have to manually define BOOST_THREAD_USE_LIB in my own program to use static linking for the Thread library (see https://svn.boost.org/trac/boost/ticket/4614), which seemed a bit off, so it's possible there's something going wrong there (although I'd expect it to affect the other aspects of the Thread library as well). William

On 2/22/2011 11:01 AM, W Frane wrote:
Do you mean more than one version of the same library, e.g., debug and release?
Not this.
manually define BOOST_THREAD_USE_LIB in my own program to use static linking for the Thread library (see https://svn.boost.org/trac/boost/ticket/4614), which seemed a bit off, so it's possible there's something going wrong there (although I'd expect it to affect the other aspects of the Thread library as well).
I don't know if this is causing a problem or not. What happened to me, many moons ago, using MSVC, was this: Main program, compiled and statically linked against the C++ runtime library DLL, compiled and statically linked against the same C++ runtime library. Then, main and DLL linked together. Then, I'd call (for example), "malloc" from the DLL, return that pointer to Main, and Main would later call "free". Since they had two distinct copies of everything in the C++ runtime, that caused a very hard to diagnose problem because the "free" would freak out when it noticed the memory wasn't from it's own pool. If you're doing something similar, and somehow getting two distinct copies of the boost::thread library hard linked into your program, I could see all sorts of ways you would be in for a world of hurt. I do not know enough about minGW to know if that's even possible to do, but I'd check. As a way to check, try doing something simple like printing out the address of a global function or a global variable in both Main and DLL. If you get different values, then you're probably in the situation of having two copies around.

On 02/16/2011 12:08 PM, W Frane wrote:
The build log output from Code Blocks is:
mingw32-g++.exe -Wall -fexceptions -g -I"C:\Program Files\boost\boost_1_45_0" -c "C:\Documents and Settings\WFrane\My Documents\C++ code\boost thread interrupt test\boost_thread_interrupt_test\main.cpp" -o obj\Debug\main.o
mingw32-g++.exe -L"C:\Program Files\boost\boost_1_45_0\stage\lib" -o bin\Debug\boost_thread_interrupt_test.exe obj\Debug\main.o "C:\Program Files\boost\boost_1_45_0\stage\lib\libboost_thread-mgw44-mt-d-1_45.a"
Perhaps you need -mthreads? - Marsh

Perhaps you need -mthreads?
- Marsh
Thank you for the suggestion, but unfortunately adding -mthreads did not resolve the issue. (Threaded programs without interrupts work fine, incidentally; it appears to be the interrupts that are causing the problem, not multithreading in general.) William

I don't think it's a boost problem. As a data point, it worked fine for me: $ g++ -static -I $BH/include/boost-1_45 -L $BH/lib crashtest.cpp \ -lboost_thread-mgw45-mt-1_45 $ ./a.exe MAIN: Created thread; sleeping now. MAIN: About to interrupt thread. MAIN: Sent interrupt to thread. THREAD: Ending. MAIN: Thread has ended. I am using MinGW 4.5.0 on WinXP: $ g++ -v Using built-in specs. COLLECT_GCC=c:\MinGW\bin\g++.exe COLLECT_LTO_WRAPPER=c:/mingw/bin/../libexec/gcc/mingw32/4.5.0/lto-wrapper.exe Target: mingw32 Configured with: ../gcc-4.5.0/configure --enable-languages=c,c++,ada,fortran,objc,obj-c++ --disable-sjlj-exceptions --with-dwarf2 --enable-shared --enable-libgomp --disable-win32-registry --enable-libstdcxx-debug --enable-version-specific-runtime-libs --disable-werror --build=mingw32 --prefix=/mingw Thread model: win32 gcc version 4.5.0 (GCC) Andy On 2/17/2011 3:39 PM, W Frane wrote:
Perhaps you need -mthreads?
- Marsh
Thank you for the suggestion, but unfortunately adding -mthreads did not resolve the issue. (Threaded programs without interrupts work fine, incidentally; it appears to be the interrupts that are causing the problem, not multithreading in general.)
William
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
participants (5)
-
Eric J. Holtman
-
Marsh Ray
-
Michael Chisholm
-
Viatcheslav.Sysoltsev@h-d-gmbh.de
-
W Frane