I have a x86_64 multithreaded application where I try to emulate avr interrupts: when interrupt occurs application and all threads are suspended while interrupt handler execute defined actions.
I thought signals were the solution to do this so I'm trying to catch SIGUSR1 signal, but when I raise SIGUSR1 program exit with a segmentation fault error before executing apply function. (I have tried mutex in isr and signals but removed as actually they run in the main thread)
The code is within 5 files.
isr.h
#ifndef __ISR_H__
#define __ISR_H__
typedef void (*routine_t)(void);
class InterruptServiceRoutine
{
routine_t routine;
bool locked = true;
public:
InterruptServiceRoutine(routine_t isr);
void apply();
void unlock(){locked = false;};
};
typedef InterruptServiceRoutine ISR_t;
#endif // __ISR_H__
isr.cpp:
#include <ISR.h>
InterruptServiceRoutine::InterruptServiceRoutine(routine_t isr): routine(isr){}
void InterruptServiceRoutine::apply()
{
if (!locked) routine();
}
Signals.h:
#ifndef __SIGNALS_H__
#define __SIGNALS_H__
#include <vector>
#include <ISR.h>
#include <signal.h>
class Logger;
class Signals
{
private:
Logger& log;
std::vector<ISR_t*> isr_table;
public:
Signals(Logger&);
~Signals();
unsigned int count(void);
void clear(void);
void connect(ISR_t &isr);
void apply(int);
};
#endif // __SIGNALS_H__
Signals.cpp:
#include <signal.h>
#include <pthread.h>
#include <functional>
#include <ISR.h>
#include <Signals.h>
#include <Logger.h>
using namespace std;
void Signals::apply(int)
{
sigset_t sigs_to_block;
sigfillset(&sigs_to_block);
pthread_sigmask(SIG_BLOCK, &sigs_to_block, NULL);
unsigned int num_interrupts = count();
for (unsigned int i=0; i < num_interrupts; ++i)
{
isr_table[i]->apply();
}
pthread_sigmask(SIG_SETMASK, NULL, NULL);
}
Signals::Signals(Logger& _log): log(_log)
{
clear();
auto _apply = bind1st(mem_fun(&Signals::apply), this);
struct sigaction new_action;
new_action.sa_handler = (__sighandler_t) &_apply;
new_action.sa_flags = 0;
sigfillset(&new_action.sa_mask);
sigaction(SIGUSR1, &new_action, NULL);
pthread_sigmask(SIG_SETMASK, NULL, NULL);
}
Signals::~Signals() {
struct sigaction new_action;
new_action.sa_handler = SIG_DFL;
new_action.sa_flags = 0;
sigemptyset(&new_action.sa_mask);
sigaddset(&new_action.sa_mask, SIGUSR1);
sigaction(SIGUSR1, &new_action, NULL);
clear();
}
void Signals::clear(void)
{
isr_table.clear();
isr_table.reserve(20);
}
unsigned int Signals::count(void)
{
return isr_table.size();
}
void Signals::connect(ISR_t &isr)
{
isr_table.push_back(&isr);
}
SignalsTest.test:
#include <signal.h>
#include <pthread.h>
#include <cxxtest/TestSuite.h>
#include <ISR.h>
#include <Signals.h>
#include <Logger.h>
volatile sig_atomic_t isr_called_count;
void isr(void)
{
++isr_called_count;
}
class SignalsTestSuite: public CxxTest::TestSuite
{
Logger log;
Signals handler;
public:
SignalsTestSuite(void): handler(log){}
void setUp()
{
handler.clear();
isr_called_count = 0;
}
/* ... truncated for more visibility ... */
void testWhenRaiseSIGUSRItCallsAvailableRoutine(void)
{
ISR_t routine(&isr);
routine.unlock();
handler.connect(routine);
handler.connect(routine);
raise(SIGUSR1);
TS_ASSERT_EQUALS(isr_called_count, 2);
}
};
Debug informations:
GNU gdb (Gentoo 7.7.1 p1) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-pc-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://bugs.gentoo.org/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./out/signals...done.
(gdb) r
Starting program: test/out/signals
warning: Could not load shared library symbols for linux-vdso.so.1.
Do you need "set solib-search-path" or "set sysroot"?
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Running 3 tests..
Program received signal SIGUSR1, User defined signal 1.
0x00007ffff7bd0beb in raise (sig=10) at ../sysdeps/unix/sysv/linux/pt-raise.c:36
36 return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid),
(gdb) bt
#0 0x00007ffff7bd0beb in raise (sig=10) at ../sysdeps/unix/sysv/linux/pt-raise.c:36
#1 0x0000000000403f38 in SignalsTestSuite::testWhenRaiseSIGUSRItCallsAvailableRoutine (this=this#entry=0x631cc0 <suite_SignalsTestSuite>)
at test/SignalsTest.test:62
#2 0x0000000000403f92 in TestDescription_suite_SignalsTestSuite_testWhenRaiseSIGUSRItCallsAvailableRoutine::runTest (this=<optimized out>) at out/signals.cpp:38
#3 0x000000000040424e in CxxTest::RealTestDescription::run (this=<optimized out>) at /opt/cxxtest/cxxtest/RealDescriptions.cpp:109
#4 0x0000000000409afb in CxxTest::TestRunner::runTest (this=this#entry=0x7fffffffd29f, td=...) at /opt/cxxtest/cxxtest/TestRunner.h:85
#5 0x0000000000409c76 in CxxTest::TestRunner::runSuite (this=this#entry=0x7fffffffd29f, sd=...) at /opt/cxxtest/cxxtest/TestRunner.h:72
#6 0x0000000000409e15 in CxxTest::TestRunner::runWorld (this=this#entry=0x7fffffffd29f) at /opt/cxxtest/cxxtest/TestRunner.h:57
#7 0x0000000000409f52 in CxxTest::TestRunner::runAllTests (listener=...) at /opt/cxxtest/cxxtest/TestRunner.h:34
#8 0x0000000000409f93 in CxxTest::ErrorFormatter::run (this=this#entry=0x7fffffffd320) at /opt/cxxtest/cxxtest/ErrorFormatter.h:59
#9 0x000000000040aa89 in CxxTest::Main<CxxTest::ErrorPrinter> (tmp=..., argc=argc#entry=1, argv=argv#entry=0x7fffffffd448) at /opt/cxxtest/cxxtest/TestMain.h:109
#10 0x0000000000407f62 in main (argc=1, argv=0x7fffffffd448) at out/runner.cpp:18
(gdb) l
31 that. */
32 pid_t pid = THREAD_GETMEM (THREAD_SELF, pid);
33 if (__glibc_unlikely (pid < 0))
34 pid = -pid;
35
36 return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid),
37 sig);
38 }
(gdb) s
Program received signal SIGSEGV, Segmentation fault.
0x00007fffffffd210 in ?? ()
(gdb) bt
#0 0x00007fffffffd210 in ?? ()
#1 <signal handler called>
#2 0x00007ffff7bd0beb in raise (sig=10) at ../sysdeps/unix/sysv/linux/pt-raise.c:36
#3 0x0000000000403f38 in SignalsTestSuite::testWhenRaiseSIGUSRItCallsAvailableRoutine (this=this#entry=0x631cc0 <suite_SignalsTestSuite>)
at test/SignalsTest.test:62
#4 0x0000000000403f92 in TestDescription_suite_SignalsTestSuite_testWhenRaiseSIGUSRItCallsAvailableRoutine::runTest (this=<optimized out>) at out/signals.cpp:38
#5 0x000000000040424e in CxxTest::RealTestDescription::run (this=<optimized out>) at /opt/cxxtest/cxxtest/RealDescriptions.cpp:109
#6 0x0000000000409afb in CxxTest::TestRunner::runTest (this=this#entry=0x7fffffffd29f, td=...) at /opt/cxxtest/cxxtest/TestRunner.h:85
#7 0x0000000000409c76 in CxxTest::TestRunner::runSuite (this=this#entry=0x7fffffffd29f, sd=...) at /opt/cxxtest/cxxtest/TestRunner.h:72
#8 0x0000000000409e15 in CxxTest::TestRunner::runWorld (this=this#entry=0x7fffffffd29f) at /opt/cxxtest/cxxtest/TestRunner.h:57
#9 0x0000000000409f52 in CxxTest::TestRunner::runAllTests (listener=...) at /opt/cxxtest/cxxtest/TestRunner.h:34
#10 0x0000000000409f93 in CxxTest::ErrorFormatter::run (this=this#entry=0x7fffffffd320) at /opt/cxxtest/cxxtest/ErrorFormatter.h:59
#11 0x000000000040aa89 in CxxTest::Main<CxxTest::ErrorPrinter> (tmp=..., argc=argc#entry=1, argv=argv#entry=0x7fffffffd448) at /opt/cxxtest/cxxtest/TestMain.h:109
#12 0x0000000000407f62 in main (argc=1, argv=0x7fffffffd448) at out/runner.cpp:18
(gdb) l
Line number 39 out of range; ../sysdeps/unix/sysv/linux/pt-raise.c has 38 lines.
(gdb) s
Cannot find bounds of current function
(gdb) c
Continuing.
Program terminated with signal SIGSEGV, Segmentation fault.
The program no longer exists.
Memory informations:
$ valgrind --leak-check=full --show-leak-kinds=all ./out/signals
==31715== Memcheck, a memory error detector
==31715== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==31715== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==31715== Command: ./out/signals
==31715==
Running 3 tests..==31715==
==31715== Process terminating with default action of signal 11 (SIGSEGV)
==31715== Bad permissions for mapped region at address 0xFFEFFF1F0
==31715== at 0xFFEFFF1F0: ???
==31715== by 0x409F92FF: ???
==31715== by 0xFFF: ???
==31715== by 0x40AA88FF: ???
==31715==
==31715== HEAP SUMMARY:
==31715== in use at exit: 176 bytes in 2 blocks
==31715== total heap usage: 2 allocs, 0 frees, 176 bytes allocated
==31715==
==31715== 16 bytes in 1 blocks are still reachable in loss record 1 of 2
==31715== at 0x4C294C0: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==31715== by 0x408AB1: CxxTest::ErrorPrinter::ErrorPrinter(std::ostream&, char const*, char const*) (ErrorPrinter.h:43)
==31715== by 0x407F4C: main (runner.cpp:17)
==31715==
==31715== 160 bytes in 1 blocks are still reachable in loss record 2 of 2
==31715== at 0x4C294C0: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==31715== by 0x40B2E3: __gnu_cxx::new_allocator<InterruptServiceRoutine*>::allocate(unsigned long, void const*) (new_allocator.h:104)
==31715== by 0x40B315: std::_Vector_base<InterruptServiceRoutine*, std::allocator<InterruptServiceRoutine*> >::_M_allocate(unsigned long) (in test/out/signals)
==31715== by 0x40B941: InterruptServiceRoutine** std::vector<InterruptServiceRoutine*, std::allocator<InterruptServiceRoutine*> >::_M_allocate_and_copy<std::move_iterator<InterruptServiceRoutine**> >(unsigned long, std::move_iterator<InterruptServiceRoutine**>, std::move_iterator<InterruptServiceRoutine**>) (stl_vector.h:1138)
==31715== by 0x40BA28: std::vector<InterruptServiceRoutine*, std::allocator<InterruptServiceRoutine*> >::reserve(unsigned long) (vector.tcc:75)
==31715== by 0x40AE7D: Signals::clear() (Signals.cpp:57)
==31715== by 0x40AF50: Signals::Signals(Logger&) (Signals.cpp:32)
==31715== by 0x403531: SignalsTestSuite::SignalsTestSuite() (in test/out/signals)
==31715== by 0x40302D: __static_initialization_and_destruction_0(int, int) (signals.cpp:18)
==31715== by 0x403144: _GLOBAL__sub_I_suite_SignalsTestSuite_init (signals.cpp:39)
==31715== by 0x4147EC: __libc_csu_init (elf-init.c:88)
==31715== by 0x5A8DA34: (below main) (libc-start.c:245)
==31715==
==31715== LEAK SUMMARY:
==31715== definitely lost: 0 bytes in 0 blocks
==31715== indirectly lost: 0 bytes in 0 blocks
==31715== possibly lost: 0 bytes in 0 blocks
==31715== still reachable: 176 bytes in 2 blocks
==31715== suppressed: 0 bytes in 0 blocks
==31715==
==31715== For counts of detected and suppressed errors, rerun with: -v
==31715== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Erreur de segmentation
I've tried to figure out why there are missing symbols (0x00007fffffffd210 in ?? () and at 0xFFEFFF1F0: ??? ...):
(gdb) info share
From To Syms Read Shared Object Library
0x00007ffff7ddca80 0x00007ffff7df5960 Yes /lib64/ld-linux-x86-64.so.2
No linux-vdso.so.1
0x00007ffff7bc6a40 0x00007ffff7bd2781 Yes /lib64/libpthread.so.0
0x00007ffff79bb360 0x00007ffff79be0dc Yes /lib64/librt.so.1
0x00007ffff770f5f0 0x00007ffff77733c3 Yes /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/libstdc++.so.6
0x00007ffff73c04f0 0x00007ffff7425266 Yes /lib64/libm.so.6
0x00007ffff71a7ac0 0x00007ffff71b6e45 Yes /usr/lib/gcc/x86_64-pc-linux-gnu/4.8.4/libgcc_s.so.1
0x00007ffff6e2c430 0x00007ffff6f53b44 Yes /lib64/libc.so.6
But can't find a way to get "linux-vdso.so.1" on gentoo.
I'm a beginner in C++ what I'm doing wrong with memory ?
Have you a tip to fix this ?
Edit1:
routine_t and __sighandler_t types are aliases for: void (*)(void)
I believe that you can safely ignore the error. A StackOverflow member with a reputation in the top 0.25% of members (!) says that this warning "Could not load shared library symbols for linux-vdso.so.1." is something you can safely ignore. To see the post, go here:
Could not load shared library symbols for linux-vdso.so.1. while debugging
Problem solved thanks to Igor Tandetnik.
Finally the following code function.
signals.h:
#ifndef __SIGNALS_H__
#define __SIGNALS_H__
#include <vector>
#include <ISR.h>
#include <signal.h>
using namespace std;
class Logger;
class Signals
{
private:
Logger& log;
static bool action_handled;
void reserve();
public:
static void start();
static void stop();
static std::vector<ISR_t*> isr_table;
Signals(Logger& _log);
~Signals();
unsigned int count(void);
void clear(void);
void connect(ISR_t&);
static void apply(int);
static void unmask_pthread_signals();
static void mask_pthread_signals();
};
#endif // __SIGNALS_H__
signals.cpp:
#include <functional>
#include <signal.h>
#include <pthread.h>
#include <ISR.h>
#include <Signals.h>
#include <Logger.h>
using namespace std;
vector<ISR_t*> Signals::isr_table={};
bool Signals::action_handled=false;
void Signals::apply(int)
{
mask_pthread_signals();
for (unsigned int i=0; i < isr_table.size(); ++i)
{
isr_table[i]->apply();
}
unmask_pthread_signals();
}
Signals::Signals(Logger& _log): log(_log){
clear();
start();
}
Signals::~Signals() {
clear();
stop();
}
void Signals::clear(void)
{
isr_table.clear();
isr_table.reserve(0);
}
unsigned int Signals::count(void)
{
return isr_table.size();
}
void Signals::start()
{
if (action_handled) return;
struct sigaction new_action;
new_action.sa_handler = (__sighandler_t) &Signals::apply;
new_action.sa_flags = 0;
sigemptyset(&new_action.sa_mask);
sigaction(SIGUSR1, &new_action, NULL);
unmask_pthread_signals();
action_handled = true;
}
void Signals::stop()
{
if (!action_handled) return;
struct sigaction new_action;
new_action.sa_handler = SIG_DFL;
sigemptyset(&new_action.sa_mask);
sigaction(SIGUSR1, &new_action, NULL);
mask_pthread_signals();
action_handled = false;
}
void Signals::unmask_pthread_signals()
{
sigset_t signals_mask;
sigemptyset(&signals_mask);
pthread_sigmask(SIG_SETMASK, &signals_mask, NULL);
}
void Signals::mask_pthread_signals()
{
sigset_t signals_mask;
sigfillset(&signals_mask);
pthread_sigmask(SIG_SETMASK, &signals_mask, NULL);
}
void Signals::reserve()
{
if (isr_table.capacity() <= isr_table.size()) {
isr_table.reserve(isr_table.capacity() + 20);
}
}
void Signals::connect(ISR_t &isr)
{
start();
reserve();
isr_table.push_back(&isr);
}
Related
Is there a way to properly run qmltestrunner against a test, that uses a custom qml module, that is compiled with address sanitizer flags (e.g. --fsanitize=address), and to be able to detect all leaks in this qmlmodule?
The problem is that qmltestrunner is not linked against the address sanitizer, thus it complains regarding the linkage order when importing custom qmlmodule.
> qmltestrunner -import ../../../../build/qmlmodules/ -platform offscreen
==393140==ASan runtime does not come first in the initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD.
When I am trying to run a qmltestrunner explicitly preloading sanitizer it detects qt internal leaks, but doesn't detect leaks in my qmlmodule:
> LD_PRELOAD=/lib/x86_64-linux-gnu/libasan.so.6 qmltestrunner -import ../../../../build/MyLib/qmlmodules/ -platform offscreen
is 0x12345********* Start testing of qmltestrunner *********
Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 10.2.1 20210110), debian 11
PASS : qmltestrunner::TestIoauExample::initTestCase()
PASS : qmltestrunner::TestIoauExample::test_ioau_example()
PASS : qmltestrunner::TestIoauExample::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 2ms
********* Finished testing of qmltestrunner *********
=================================================================
==447337==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 500 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f3417a7 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x7f3f06f6950a in ioau::IoauTester::HeightmapGenerator::HeightmapGenerator(QObject*) (/home/ifolbort/localstorage/workspace/ioau-testbed2/ioau/build/monolith/build/ioau/qmlmodules/IoauTester/libioautester-qmlplugin.so+0x1550a)
#2 0x7f3f06f62223 in void QQmlPrivate::createInto<ioau::IoauTester::HeightmapGenerator>(void*) (/home/ifolbort/localstorage/workspace/ioau-testbed2/ioau/build/monolith/build/ioau/qmlmodules/IoauTester/libioautester-qmlplugin.so+0xe223)
#3 0x7f3f0d4e2c89 in QQmlType::create(QObject**, void**, unsigned long) const (/lib/x86_64-linux-gnu/libQt5Qml.so.5+0x291c89)
#4 0x7f3f0d4c127c in QQmlComponent::QQmlComponent(QQmlEngine*, QObject*) (/lib/x86_64-linux-gnu/libQt5Qml.so.5+0x27027c)
Indirect leak of 168 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f0dd51b53 in QScreen::QScreen(QPlatformScreen*) (/lib/x86_64-linux-gnu/libQt5Gui.so.5+0x165b53)
Indirect leak of 88 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f0efb8d04 in QObject::QObject(QObject*) (/lib/x86_64-linux-gnu/libQt5Core.so.5+0x2e2d04)
Indirect leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f076610a8 (/usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqoffscreen.so+0x120a8)
Indirect leak of 24 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f07662167 (/usr/lib/x86_64-linux-gnu/qt5/plugins/platforms/libqoffscreen.so+0x13167)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f0ede4bb0 in QtSharedPointer::ExternalRefCountData::getAndRef(QObject const*) (/lib/x86_64-linux-gnu/libQt5Core.so.5+0x10ebb0)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f0dd01422 in QWindowSystemInterface::handleScreenAdded(QPlatformScreen*, bool) (/lib/x86_64-linux-gnu/libQt5Gui.so.5+0x115422)
#2 0x7773c9c2beee67ff (<unknown module>)
Indirect leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f3f0f341647 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99
#1 0x7f3f0dd0cadb in QPlatformScreen::QPlatformScreen() (/lib/x86_64-linux-gnu/libQt5Gui.so.5+0x120adb)
SUMMARY: AddressSanitizer: 868 byte(s) leaked in 8 allocation(s).
When I disable Asan linkage order verification test qmltestrunner passes tests, but my leak is not detected:
> ASAN_OPTIONS=verify_asan_link_order=false qmltestrunner -import ../../../../build/MyLib/qmlmodules/ -platform offscreen
is 0x12345********* Start testing of qmltestrunner *********
Config: Using QtTest library 5.15.2, Qt 5.15.2 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 10.2.1 20210110), debian 11
PASS : qmltestrunner::TestIoauExample::initTestCase()
PASS : qmltestrunner::TestIoauExample::test_ioau_example()
PASS : qmltestrunner::TestIoauExample::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 2ms
********* Finished testing of qmltestrunner *********
qml source file with TestCase i am trying to run:
import QtQuick 2.0
import QtTest 1.2
import MyLibTester 0.1
Item {
TestCase {
name: "TestMyLibExample"
when: heightmapGenerator.ready
function test_mylib_example() {
verify(heightmapGenerator.ready)
}
}
resources: HeightmapGenerator {
id: heightmapGenerator
property bool loaded: false
property bool ready: false
Component.onCompleted: {
ready = true
loaded = true
}
}
}
a leak that I am trying to introduce and which is not detected when running qmltestrunner
--- a/mylib/qmlmodules/MyLibTester/src/HeightmapGenerator.cpp
+++ b/mylib/qmlmodules/MyLibTester/src/HeightmapGenerator.cpp
## -9,6 +9,8 ##
+#include "../tests/leak_tst.h"
namespace mylib
{
namespace MyLibTester
## -35,10 +37,13 ## static float cubicSpline(float x)
}
-
HeightmapGenerator::HeightmapGenerator(QObject* parent)
: QObject(parent)
{
+ auto test_leak = leak_test(500);
+ std::cout << "is "
+ << (test_leak == reinterpret_cast<bool*>(0x12345) ? "NOT" : "")
+ << "0x12345";
}
However, when I compile a simple app with the same leak introduced sanitizer is able to detect the leak:
//leak_tst.h
#ifndef leak_tst
#define leak_tst
bool* leak_test(int n)
{
return new bool[n];
}
#endif
///leak_tst.cpp
#include "leak_tst.h"
#include <iostream>
int main()
{
auto test_leak = leak_test(500);
std::cout << "is "
<< (test_leak == reinterpret_cast<bool*>(0x12345) ? "NOT" : "")
<< "0x12345";
return 0;
}
> leak_tst
is 0x12345
=================================================================
==419360==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 500 byte(s) in 1 object(s) allocated from:
#0 0x7fb68db4b7a7 in operator new[](unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:102
#1 0x55b8687e3132 in main (/home/ifolbort/localstorage/workspace/ioau-testbed2/ioau/build/monolith/build/ioau/qmlmodules/IoauTester/tests/test-leak+0x1132)
#2 0x7fb68d734d09 in __libc_start_main ../csu/libc-start.c:308
SUMMARY: AddressSanitizer: 500 byte(s) leaked in 1 allocation(s).
I'm trying to make a simple freeglut application. I have the following code:
#include "GL/freeglut.h"
#include "glm/glm.hpp"
// global and state variables
namespace globals {
const int screen_width = 720;
const int screen_height = 720;
const int window_position_x = 100;
const int window_position_y = 100;
const glm::vec4 clear_color (0.2f, 0.2f, 0.2f, 1.0f);
}
void display ();
int main (int argc, char** argv) {glutInit(&argc, argv);
// initialize GLUT window size, position, display mode
glutInitWindowSize(globals::screen_width, globals::screen_height);
glutInitWindowPosition(globals::window_position_x, globals::window_position_y);
glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
// continue execution after window is closed by user
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
// create a window
glutCreateWindow("Simple GLUT Template");
// setup a display callback that GLUT calls for every render
glutDisplayFunc(display);
// start main loop
glutMainLoop();
return 0;
}
void display () {
using namespace globals;
glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a);
glClear(GL_COLOR_BUFFER_BIT);
glutSwapBuffers();
}
I initialise the program to work with GLUT and create a simple window. For compilation, I use this:
g++ -Wall -Wextra -pedantic -g -DDEBUG_MODE -D_GLIBCXX_DEBUG -fsanitize=address,undefined -lGL -lGLU -lglut simple-glut-template.cpp -o simple-glut-template
When I execute the program and close the window, the address sanitizer seems to pick up on a lot of memory leakage that I cannot seem to fix (output shared below). Any help on understanding what's happening is appreciated. Thanks!
Memory leak found by Address Sanitizer:
=================================================================
==24070==ERROR: LeakSanitizer: detected memory leaks
Indirect leak of 1264 byte(s) in 2 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f2998557701 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd57701)
#2 0x7f299855a86c (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd5a86c)
Indirect leak of 632 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f2998557701 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd57701)
#2 0x7f299855a1d7 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd5a1d7)
Indirect leak of 520 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f29978b2317 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xb2317)
Indirect leak of 416 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f299ba65b04 (/lib/x86_64-linux-gnu/libGLX_mesa.so.0+0x42b04)
Indirect leak of 416 byte(s) in 2 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f299854729e (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd4729e)
#2 0x7f2998549caf (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd49caf)
#3 0x7f299855a8eb (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd5a8eb)
Indirect leak of 120 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f299ba7187f (/lib/x86_64-linux-gnu/libGLX_mesa.so.0+0x4e87f)
Indirect leak of 96 byte(s) in 2 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f299854e18c (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd4e18c)
Indirect leak of 96 byte(s) in 2 object(s) allocated from:
#0 0x7f299c8b78d5 in __interceptor_realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85
#1 0x7f299855df80 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd5df80)
#2 0x7f299854cf16 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd4cf16)
Indirect leak of 88 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f29978ad39d (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xad39d)
Indirect leak of 88 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f299c3009ce in xcb_register_for_special_xge (/lib/x86_64-linux-gnu/libxcb.so.1+0xe9ce)
Indirect leak of 80 byte(s) in 2 object(s) allocated from:
#0 0x7f299c8b89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x7f299c301872 (/lib/x86_64-linux-gnu/libxcb.so.1+0xf872)
Indirect leak of 56 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x7f29978b55fc (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xb55fc)
Indirect leak of 40 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b83b7 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:77
#1 0x7f299854cd45 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd4cd45)
Indirect leak of 32 byte(s) in 2 object(s) allocated from:
#0 0x7f299c8b89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x7f299c301ab5 (/lib/x86_64-linux-gnu/libxcb.so.1+0xfab5)
Indirect leak of 8 byte(s) in 1 object(s) allocated from:
#0 0x7f299c8b89cf in __interceptor_malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
#1 0x7f299854d7aa (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd4d7aa)
#2 0x7f299855d270 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd5d270)
#3 0x7f299854ca7f (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0xd4ca7f)
#4 0x7f2997985729 (/usr/lib/x86_64-linux-gnu/dri/iris_dri.so+0x185729)
SUMMARY: AddressSanitizer: 3952 byte(s) leaked in 21 allocation(s).
I have a project requiring the use of Maxon EPOS under Linux. They provide libraries and code to integrate under Linux. Links are available below, 2 files libEposCmd.so and libftd2xx.so to copy into /etc/local/lib and /etc/lib and a Definition.h file.
After following the procedure, compiling the file HelloEposCmd.cpp and trying the program to test communication with hardware via USB, the code gets a Segmentation fault.
I have tried the same procedure on other machines, with Ubuntu 14.04 and 16.04 without trouble. So at this point I am not sure what is the problem, my machine, the code, issue with USB or something else.
If that can help, my laptop is a MSI Gl62 and running on Ubuntu 16.04LTS 64 bits. I am not very familiar with Ubuntu.
You can find the 2 library files, Definition.h file and the HelloEposCmd.cpp file.
http://www.maxonmotor.com/medias/sys_master/root/8815100330014/EPOS-Linux-Library-En.zip
And the installation guide: http://www.maxonmotor.com/medias/sys_master/root/8821690073118/EPOS-Command-Library-En.pdf at 9-Integration paragraph.
Here is a sample of the code:
#include <iostream>
#include "Definitions.h"
#include <string.h>
#include <sstream>
#include <unistd.h>
#include <getopt.h>
#include <stdlib.h>
#include <stdio.h>
#include <list>
#include <math.h>
typedef void* HANDLE;
typedef int BOOL;
using namespace std;
void* g_pKeyHandle = 0;
unsigned short g_usNodeId = 1;
string g_deviceName;
string g_protocolStackName;
string g_interfaceName;
string g_portName;
int g_baudrate = 0;
const string g_programName = "HelloEposCmd";
#ifndef MMC_SUCCESS
#define MMC_SUCCESS 0
#endif
#ifndef MMC_FAILED
#define MMC_FAILED 1
#endif
#ifndef MMC_MAX_LOG_MSG_SIZE
#define MMC_MAX_LOG_MSG_SIZE 512
#endif
void LogError(string functionName, int p_lResult, unsigned int p_ulErrorCode);
void LogInfo(string message);
void PrintUsage();
void PrintHeader();
void PrintSettings();
int OpenDevice(unsigned int* p_pErrorCode);
int CloseDevice(unsigned int* p_pErrorCode);
void SetDefaultParameters();
int ParseArguments(int argc, char** argv);
int DemoProfilePositionMode(HANDLE p_DeviceHandle, unsigned short p_usNodeId, unsigned int & p_rlErrorCode);
int Demo(unsigned int* p_pErrorCode);
The function where the Segfault appears:
int OpenDevice(unsigned int* p_pErrorCode)
{
int lResult = MMC_FAILED;
char* pDeviceName = new char[255];
char* pProtocolStackName = new char[255];
char* pInterfaceName = new char[255];
char* pPortName = new char[255];
strcpy(pDeviceName, g_deviceName.c_str());
strcpy(pProtocolStackName, g_protocolStackName.c_str());
strcpy(pInterfaceName, g_interfaceName.c_str());
strcpy(pPortName, g_portName.c_str());
LogInfo("Open device...");
g_pKeyHandle = VCS_OpenDevice(pDeviceName, pProtocolStackName, pInterfaceName, pPortName, p_pErrorCode);
if(g_pKeyHandle!=0 && *p_pErrorCode == 0)
{
unsigned int lBaudrate = 0;
unsigned int lTimeout = 0;
if(VCS_GetProtocolStackSettings(g_pKeyHandle, &lBaudrate, &lTimeout, p_pErrorCode)!=0)
{
if(VCS_SetProtocolStackSettings(g_pKeyHandle, g_baudrate, lTimeout, p_pErrorCode)!=0)
{
if(VCS_GetProtocolStackSettings(g_pKeyHandle, &lBaudrate, &lTimeout, p_pErrorCode)!=0)
{
if(g_baudrate==(int)lBaudrate)
{
lResult = MMC_SUCCESS;
}
}
}
}
}
else
{
g_pKeyHandle = 0;
}
delete []pDeviceName;
delete []pProtocolStackName;
delete []pInterfaceName;
delete []pPortName;
return lResult;
}
The main:
int main(int argc, char** argv)
{
int lResult = MMC_FAILED;
unsigned int ulErrorCode = 0;
PrintHeader();
SetDefaultParameters();
if((lResult = ParseArguments(argc, argv))!=MMC_SUCCESS)
{
return lResult;
}
PrintSettings();
if((lResult = OpenDevice(&ulErrorCode))!=MMC_SUCCESS)
{
LogError("OpenDevice", lResult, ulErrorCode);
return lResult;
}
if((lResult = PrepareDemo(&ulErrorCode))!=MMC_SUCCESS)
{
LogError("PrepareDemo", lResult, ulErrorCode);
return lResult;
}
if((lResult = Demo(&ulErrorCode))!=MMC_SUCCESS)
{
LogError("Demo", lResult, ulErrorCode);
return lResult;
}
if((lResult = CloseDevice(&ulErrorCode))!=MMC_SUCCESS)
{
LogError("CloseDevice", lResult, ulErrorCode);
return lResult;
}
return lResult;
}
The result from gdb backtrace:
~/EPOS_Linux_Library/example/src$ gdb HelloEposCmd coreGNU gdb (Ubuntu 7.11.1-0ubuntu1~16.04) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from HelloEposCmd...(no debugging symbols found)...done.
[New LWP 2436]
[New LWP 2437]
[New LWP 2439]
[New LWP 2440]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `./HelloEposCmd'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00007fc3eca0a960 in _xend ()
at ../sysdeps/unix/sysv/linux/x86/elision-unlock.c:33
33 ../sysdeps/unix/sysv/linux/x86/elision-unlock.c: No such file or directory.
[Current thread is 1 (Thread 0x7fc3edcbc740 (LWP 2436))]
(gdb) backtrace
#0 0x00007fc3eca0a960 in _xend ()
at ../sysdeps/unix/sysv/linux/x86/elision-unlock.c:33
#1 __lll_unlock_elision (lock=0x10a1138, private=0)
at ../sysdeps/unix/sysv/linux/x86/elision-unlock.c:29
#2 0x00007fc3ec7e2934 in EventDestroy () from /usr/local/lib/libftd2xx.so
#3 0x00007fc3ec7db2e8 in FT_Close () from /usr/local/lib/libftd2xx.so
#4 0x00007fc3ec7e166b in FT_CreateDeviceInfoList ()
from /usr/local/lib/libftd2xx.so
#5 0x00007fc3ed82c911 in CMmcFtd2xxHndlBase::CreateDeviceInfoList(unsigned int*) () from /usr/local/lib/libEposCmd.so
#6 0x00007fc3ed82ca88 in CMmcFtd2xxHndlBase::GetDeviceInfos(std::list<CUsbDeviceInfo*, std::allocator<CUsbDeviceInfo*> >&, unsigned short, unsigned short) ()
from /usr/local/lib/libEposCmd.so
#7 0x00007fc3ed7e2346 in CGatewayUSBToFtd2xxDrv::GetDeviceInfos(std::list<CUsbDeviceInfo*, std::allocator<CUsbDeviceInfo*> >&) ()
from /usr/local/lib/libEposCmd.so
#8 0x00007fc3ed7e2b48 in CGatewayUSBToFtd2xxDrv::InitPortList() ()
from /usr/local/lib/libEposCmd.so
#9 0x00007fc3ed7deed1 in CPort_USB::InitGateway(CStdStr<char>, CGatewayIToDrv*) () from /usr/local/lib/libEposCmd.so
#10 0x00007fc3ed7df232 in CPort_USB::InitPort(CStdStr<char>, CGatewayIToDrv*, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#11 0x00007fc3ed7cb04f in CInterface_USB::InitPort(CStdStr<char>, CErrorInfo*)
---Type <return> to continue, or q <return> to quit---
() from /usr/local/lib/libEposCmd.so
#12 0x00007fc3ed7cb19e in CInterface_USB::InitInterface(CStdStr<char>, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#13 0x00007fc3ed7caada in CInterface_USB::InitInterface(CErrorInfo*) ()
from /usr/local/lib/libEposCmd.so
#14 0x00007fc3ed7a6a92 in CInterfaceManager::I_InitInterface(CStdStr<char>, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#15 0x00007fc3ed7923ec in CProtocolStackBase::InitProtocolStack(CStdStr<char>, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#16 0x00007fc3ed7646e9 in CProtocolStackManager::PS_InitProtocolStack(CStdStr<char>, CStdStr<char>, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#17 0x00007fc3ed73ce84 in CDeviceBase::InitDevice(CStdStr<char>, CStdStr<char>, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#18 0x00007fc3ed6d06de in CDeviceCommandSetManager::DCS_InitDevice(CStdStr<char>, CStdStr<char>, CStdStr<char>, CErrorInfo*) ()
from /usr/local/lib/libEposCmd.so
#19 0x00007fc3ed6aebd6 in CVirtualDeviceBase::InitVirtualDevice(CStdStr<char>, CStdStr<char>, CStdStr<char>, CErrorInfo*) () from /usr/local/lib/libEposCmd.so
#20 0x00007fc3ed684deb in CVirtualCommandSet_Manager::VCS_InitVirtualDevice(CStdStr<char>, CStdStr<char>, CStdStr<char>, CStdStr<char>, CErrorInfo*) ()
from /usr/local/lib/libEposCmd.so
#21 0x00007fc3ed66d112 in CCommunicationModel::CreateVirtualCommandSetManager()
() from /usr/local/lib/libEposCmd.so
---Type <return> to continue, or q <return> to quit---
#22 0x00007fc3ed67ca75 in VCS_OpenDevice () from /usr/local/lib/libEposCmd.so
#23 0x000000000040206e in OpenDevice(unsigned int*) ()
#24 0x0000000000403a6c in main ()
For USB communication, I modified the 99-ftdi.rules file provided:
SUBSYSTEM=="usb|usb_device", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a8b0", GROUP="dialout", MODE="666", SYMLINK+="ftd2xx%n"
and copied to "/etc/udev/rules.d/" (this works with other machines).
Thanks for the help
Update:
Using the newest version of FTDI (1.3.6) did not help.
Since it is specific to my machine, here are the specs, if that can help:
-Dual boot Windows 10 - Ubuntu 16.04LTS 64bits
- Intel Core i7-6700HQ CPU 2.60GHw
- Nividia GTX950M
I have read issues of elision-unlock with Intel cores and maybe also caused by the graphic card, though I don't fully understand the issues, and how this simple program is related to the graphic card, or even using multiple cores.
Make sure your USB device gets enough power from the USB port. Try supplying external power if possible.
If the device does not have external power supply, try using a USB hub with external power supply.
In my experience, if the USB device draws too much current, it can cause temporary shut down to USB powered device (e.g., 5V supply dips below 3v due to sudden high current draw, causing the device to reset, where the PC thinks it got unplugged).
I have a simple multi-threaded version with TBB which works fine on a linux machine but on occasions, not always, gives segmentation fault when executed on windows.
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
#include <math.h>
#include <dirent.h>
#include <string.h>
#include <chrono>
using namespace cv;
std::vector<std::string> fnames;
class Parallel_process : public cv::ParallelLoopBody
{
public:
Parallel_process() {}
void operator()(const cv::Range &r) const {
cv::Mat src, dst, color_dst;
if(!(src=imread(fnames[r.start], 0)).data)
{
return;
}
Canny( src, dst, 50, 200, 3 );
cvtColor( dst, color_dst, CV_GRAY2BGR );
std::vector<Vec4i> lines;
HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
for( size_t i = 0; i < lines.size(); i++ )
line( color_dst, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 );
std::string ext = "_parallel.bmp";
std::size_t found = fnames[r.start].find_last_of("/\\");
std::string fname = fnames[r.start].substr(found+1);
std::string out_fname = fname.substr(0, fname.find(".")) + ext;
cv::imwrite(out_fname.c_str(), color_dst);
}
};
int main()
{
DIR *dir;
struct dirent *ent;
std::string prefix = "c:\\Users\\foo\\Desktop\\sample_code\\imgs";
if ((dir = opendir (prefix.c_str())) != NULL) {
while ((ent = readdir (dir)) != NULL) {
fnames.push_back(prefix + '\\' + std::string(ent->d_name));
}
closedir (dir);
}
auto begin = std::chrono::high_resolution_clock::now();
cv::parallel_for_(cv::Range(0, fnames.size()), Parallel_process());
auto end = std::chrono::high_resolution_clock::now();
std::cout<<std::chrono::duration_cast<std::chrono::seconds>(end-begin).count()<<"secs"<<std::endl;
return(0);
}
Compilation is done using:
g++ -o parallel -I"c:\opencv\mingw_bld\install\include" edge_detection_parallel.cpp -L"c:\opencv\mingw_bld\install\x86\mingw\lib" -lopencv_imgproc300 -lopencv_core300 -lopencv_imgcodecs300 -lopencv_highgui300 -std=c++11
TBB version:
// Marketing-driven product version
#define TBB_VERSION_MAJOR 4
#define TBB_VERSION_MINOR 4
// Engineering-focused interface version
#define TBB_INTERFACE_VERSION 9000
#define TBB_INTERFACE_VERSION_MAJOR TBB_INTERFACE_VERSION/1000
// The oldest major interface version still supported
// To be used in SONAME, manifests, etc.
#define TBB_COMPATIBLE_INTERFACE_VERSION 2
GDB output (two runs; one was fine and the other received the segmentation fault):
gdb parallel.exe
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from C:\Users\foo\Desktop\sample_code\parallel.exe...(no
debugging symbols found)...done.
(gdb) r
Starting program: C:\Users\foo\Desktop\sample_code/parallel.exe
[New Thread 5788.0xb90]
[New Thread 5788.0x144c]
[New Thread 5788.0x168c]
[New Thread 5788.0xd1c]
30secs
[Inferior 1 (process 5788) exited normally]
(gdb) r
Starting program: C:\Users\foo\Desktop\sample_code/parallel.exe
[New Thread 620.0x1450]
[New Thread 620.0xf04]
[New Thread 620.0x100c]
[New Thread 620.0x159c]
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 620.0x159c]
0x777cd9e5 in ?? ()
(gdb) bt
#0 0x777cd9e5 in ?? ()
#1 0x777cd3d8 in ?? ()
#2 0x7787184a in ?? ()
#3 0x778319c7 in ?? ()
#4 0x777cd3d8 in ?? ()
#5 0x7541b0f9 in msvcrt!free () from C:\Windows\system32\msvcrt.dll
#6 0x00740000 in ?? ()
#7 0x6c372f3b in cv::Canny(cv::_InputArray const&, cv::_OutputArray const&, dou
ble, double, int, bool) ()
from C:\opencv\mingw_bld\bin\libopencv_imgproc300.dll
#8 0x00408ef6 in Parallel_process::operator()(cv::Range const&) const ()
#9 0x69824e46 in tbb::interface7::internal::start_for<tbb::blocked_range<int>,
(anonymous namespace)::ProxyLoopBody, tbb::auto_partitioner const>::execute()
() from C:\opencv\mingw_bld\bin\libopencv_core300.dll
#10 0x678d7e49 in tbb::internal::custom_scheduler<tbb::internal::IntelSchedulerT
raits>::local_wait_for_all (this=0x913e80, parent=..., child=0x947620)
at ../../src/tbb/custom_scheduler.h:463
#11 0x678cc94f in tbb::internal::arena::process (this=this#entry=0x93ed00,
s=...) at ../../src/tbb/arena.cpp:114
#12 0x678cbcc1 in tbb::internal::market::process (this=<optimized out>, j=...)
at ../../src/tbb/market.cpp:494
#13 0x678c86dc in tbb::internal::rml::private_worker::run (
this=this#entry=0x93fc00) at ../../src/tbb/private_server.cpp:275
#14 0x678c8893 in tbb::internal::rml::private_worker::thread_routine (
arg=0x93fc00) at ../../src/tbb/private_server.cpp:228
#15 0x75427fb0 in msvcrt!_cexit () from C:\Windows\system32\msvcrt.dll
#16 0x0093fc00 in ?? ()
#17 0x754280f5 in msvcrt!_beginthreadex () from C:\Windows\system32\msvcrt.dll
#18 0x75b04198 in KERNEL32!BaseThreadInitThunk ()
from C:\Windows\system32\kernel32.dll
#19 0x777e445d in ?? ()
#20 0x777e442b in ?? ()
#21 0x00000000 in ?? ()
OS details:
I'm having trouble using boost_threads with clang. The clang version is 3.6.0 and boost version is 1.55.0 from the new Ubuntu 15.04. Program that used to work with previous versions of clang now segfaults at startup. There is no problems when I use g++ instead.
Here is an example program to illustrate the point.
#include <iostream>
#include <boost/thread.hpp>
using namespace std;
void output() {
try {
int x = 0;
for (;;) {
boost::this_thread::sleep(boost::posix_time::milliseconds(100));
cerr << x++ << endl;
}
} catch (boost::thread_interrupted&) {}
}
int main(int argc, char* argv[]) {
try {
boost::thread output_worker(output);
boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
output_worker.interrupt();
output_worker.join();
} catch (...) {
cerr << "Unexpected error!" << endl;
exit(1);
}
}
If I compile it with g++ it works, i.e.
g++ thread.cpp -lboost_thread -lboost_system
If I compile it with clang
clang++ thread.cpp -lboost_thread -lboost_system
I get a segfault with the gdb trace below
Starting program: /home/dejan/test/a.out
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7bd0580 in boost::exception_ptr boost::exception_detail::get_static_exception_object<boost::exception_detail::bad_alloc_>() ()
from /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.55.0
(gdb) bt
#0 0x00007ffff7bd0580 in boost::exception_ptr boost::exception_detail::get_static_exception_object<boost::exception_detail::bad_alloc_>() ()
from /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.55.0
#1 0x00007ffff7bcb16a in ?? () from /usr/lib/x86_64-linux-gnu/libboost_thread.so.1.55.0
#2 0x00007ffff7de95ba in call_init (l=<optimized out>, argc=argc#entry=1, argv=argv#entry=0x7fffffffdf98, env=env#entry=0x7fffffffdfa8)
at dl-init.c:72
#3 0x00007ffff7de96cb in call_init (env=<optimized out>, argv=<optimized out>, argc=<optimized out>, l=<optimized out>) at dl-init.c:30
#4 _dl_init (main_map=0x7ffff7ffe188, argc=1, argv=0x7fffffffdf98, env=0x7fffffffdfa8) at dl-init.c:120
#5 0x00007ffff7dd9d0a in _dl_start_user () from /lib64/ld-linux-x86-64.so.2
#6 0x0000000000000001 in ?? ()
#7 0x00007fffffffe2fe in ?? ()
#8 0x0000000000000000 in ?? ()
Am I doing something wrong?
Compiling using clang -std=c++11 makes boost change its internal implementation and actually solves the segmentation fault.
It is not an ideal solution, but it is the way I will be going with our code.