I tried to build my application with ltalloc. I tried it with MinGW32 4.9.1 and MinGW64-32 4.9.2.
It compiles and links fine but when I run it a Segmentation Fault occurs. Debugging pinpointed the problem to the following code:
#include <pthread.h>
#pragma weak pthread_once
#pragma weak pthread_key_create
#pragma weak pthread_setspecific
static pthread_key_t pthread_key;
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
static void init_pthread_key() { pthread_key_create(&pthread_key, release_thread_cache); }
static thread_local int thread_initialized = 0;
static void init_pthread_destructor()//must be called only when some block placed into a thread cache's free list
{
if (unlikely(!thread_initialized))
{
thread_initialized = 1;
if (pthread_once)
{
pthread_once(&init_once, init_pthread_key); // <--- THIS CAUSES THE SEGSEGV
pthread_setspecific(pthread_key, (void*)1);//set nonzero value to force calling of release_thread_cache() on thread terminate
}
}
}
As far as I know both versions support thread-local storage natively. The Wiki of of ltalloc also wrote the following:
Warning: in some builds of MinGW there is a problem with emutls and order of execution of thread destructor (all thread local variables destructed before it), and termination of any thread will lead to application crash.
Unfortunately this warning doesn't tell me anything. Googling it also didn't make me smarter.
Out of the blue, try this:
static void init_pthread_key(void)
{
if (pthread_key_create)
{
pthread_key_create(&pthread_key, release_thread_cache);
}
}
Also adding full error checking to the pthread_* might not only help during debugging.
Related
After attempting to implement the necessary annotations to an existing codebase, I was unable to remove a seemingly simple warning. I backed into the most simple example, and still no joy.
I have cut-and-pasted the mutex.h header exactly as specified at Thread Safety Analysis. I cannot seem to do a scoped lock without producing a warning. Here is the code:
#include "mutex.h"
#include <iostream>
// functions added just to complete the implementation
void Mutex::Lock()
{
}
void Mutex::GenericUnlock()
{
}
// test a scoped lock
void do_something(Mutex &m)
{
auto locker = MutexLocker(&m);
std::cout << "Hello, world!\n";
}
int main(int argc, char** argv)
{
Mutex my_mutex;
do_something(my_mutex);
}
Compiling with clang++ -o thread_static_analysis thread_static_analysis.cpp -std=c++17 -Wthread-safety produces the following warning:
thread_static_analysis.cpp:18:1: warning: releasing mutex 'locker' that was not held [-Wthread-safety-analysis]
}
^
1 warning generated.
Either (1) I am missing something, or (2) this is a false-positive that must be ignored until a clang implementation issue is resolved. A search for such issues has as-yet given no useful results.
clang version 10.0.0-4ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix
My understanding is that you are potentially creating a copy of temporary MutexLocker object in
auto locker = MutexLocker(&m);
(or thread safety analysis thinks you are creating it). The temporary is then destroyed and calls m.Unlock(). Then at the end of the function the locker object is destroyed and calls m.Unlock() again (thus causing a double release error).
I am running into a weird issue at work where after updating from RHEL 7 (linux kernel 3.10.0, GCC 4.8.5) to RHEL 8 (linux kernel 4.18.0, GCC 8.3.1), our enums have started to cause problems while destructing. From my best diagnosis in gdb, it is trying to call the destructor on the same static object more than once (once for each lib that instantiates the enums and is used to build the executable in question) and segfaulting on the second attempt, as the object has already been destroyed.
Here is the backtrace:
#0 0x0000000000000000 in ?? ()
#1 0x00007ffff3c91b6f in __tcf_2 () at /sourcepath/ExampleEnum.H:106
#2 0x00007ffff68ae3c7 in __cxa_finalize () from /lib64/libc.so.6
#3 0x00007ffff3c33c87 in __do_global_dtors_aux () from /libpath/lib64/libsecond_lib.so
#4 0x00007fffffff9c10 in ?? ()
#5 0x00007ffff7de42a6 in _dl_fini () from /lib64/ld-linux-x86-64.so.2
This is the second time it reaches that line of ExampleEnum.H in __tcf_2, a function related to static destruction. The first time is no problem.
Here is the structure of the enums:
#ifndef _EXAMPLEENUM_H
#define _EXAMPLEENUM_H
#include "OurString.H"
#define EXAMPLEENUM_SOURCE_LIST(enum) \
enum(THIS_EXAMPLE_ENUM, "THIS_EXAMPLE", "", false),\
enum(ExampleEnumMax, "ExampleEnumMax", "error", false)
#define NAME_GENERATOR(name, guiname, description, p4) name
#define GUI_NAME_STR_GENERATOR(name, guiname, description, p4) guiname
class Example {
public:
enum Enum {
EXAMPLEENUM_SOURCE_LIST(NAME_GENERATOR)
};
static const int NUM_FIELDS = ExampleEnumMax + 1;
static const char* names[NUM_FIELDS];
};
typedef Example::Enum ExampleEnum
extern const OurString ExampleEnum_GuiName[Example::ExampleEnumMax + 1];
#ifdef CONSTRUCT_ENUM_STRINGS
const OurString ExampleEnum_GuiName[Example::ExampleEnumMax + 1] = {
EXAMPLEENUM_SOURCE_LIST(GUI_NAME_STR_GENERATOR)
};
#endif
#endif
And then in the libs where it is used, this names.C is compiled into the lib:
#define CONSTRUCT_ENUM_STRINGS 1
#include <enumpath/ExampleEnum.H>
#undef CONSTRUCT_ENUM_STRINGS
const char* Example::names[Example::NUM_FIELDS] = {
EXAMPLEENUM_SOURCE_LIST(GUI_NAME_STR_GENERATOR)
};
We have a band-aid solution that basically just covers up the problem, ie calling _exit(0) at the end of main() skips all destructors, including static destructors which pose the problem so it doesn't segfault. However, obviously we want to fix the way our enums are handled such that we can run all necessary destructors (and no more than necessary) without segfaulting.
Is there anything obviously wrong with our enums? They have been working through several kernel/gcc versions and have only recently posed a problem.
Is there likely to be anything wrong with how they are used in the libs? This problem only occurs when an executable is compiled with multiple libs that use the same enum, which is unfortunately quite often. Is there some strict tree of import dependency structure we could keep to to fix this?
Why did it work up until we updated the OS?
EDIT:
Concerns about OurString's destructor have been raised, I didn't include it because it was trivial:
~OurString() throw () {}
ALSO: a little more debugging and going through a version compiled by GCC 4.8.5 that doesn't segfault shows me that __tcf_2 is entered twice there too, so my theory about improperly calling the destructor multiple times is wrong, and it looks like #PaulMcKenzie's theory of static initialization order is likely.
Thanks in advance!
I've been porting some c++ app from Visual Studio 2013 to Visual Studio 2017. Aside from the plethora of new warnings that I had to fix, the compilation and linking went okay.
However, when running the app, it 'stalled' when trying to re-enter the constructor of a singleton (when successive function calls form a loop back to the constructor). It seems that this behaviour was okay in VS2013, but is no longer valid in VS2017. There is no error message.
I'm aware of all the bad things related to singletons, and that there should at least not be loops. The question is not there.
Is there a way to tell the VS2017 compiler that I'd like to shoot myself in the foot, and allow the same behaviour that was there in VS2013?
I don't have access to the code that causes this behaviour because it comes from a third-party library, this is why I can't 'just fix it', unfortunately.
Here is an example which works in VS2013, but doesn't work in VS2017:
main.cpp
#include "Singleton.h";
int
main( void )
{
std::cout << "let's do this!" << std::endl;
int two = Singleton::GetReference().getTwo();
std::cout << "ok" << std::endl;
return 0;
}
Singleton.h
#pragma once
class Stuff;
class Singleton
{
public:
static Singleton& GetReference();
int getTwo() { return 2; }
private:
Singleton();
Stuff* stuff;
};
Singleton.cpp
#include "Singleton.h"
#include "Stuff.h"
Singleton&
Singleton::GetReference() {
static Singleton theInstance;
return theInstance;
}
Singleton::Singleton()
{
stuff = new Stuff();
}
Stuff.h
#pragma once
class Stuff
{
public:
Stuff();
private:
int two;
};
Stuff.cpp
#include "Stuff.h"
#include "Singleton.h"
Stuff::Stuff()
{
two = Singleton::GetReference().getTwo();
}
In the code above, when step-by-step debugging, the first time we get on the line static Singleton theInstance; will work as expected, but the second time, a F11 will go to the file thread_safe_statics.cpp, into the method extern "C" void __cdecl _Init_thread_header(int* const pOnce). A Shift+F11 will exit the method and the program will wait indefinitely at the line specified (observed when pausing the program from the debugger).
PS
This issue probably occurs in Visual Studio 2015 too, as the documentation linked from the accepted answer mentions VS2015.
/Zc:threadSafeInit-
The general "Conformance" page is MSDN: Conformance, which details which new features you can disable.
I needed the code for sizedDealloc, where my new compiler was creating a sized new operator for a library which broke older compiled expectations.
As this is a compile flag, at least some of the code would be in your control, and you should be able to unravel the beast.
The constructor Stuff::Stuff is calling a function on an incompletely constructed object.
That would create "Undefined behavior". If the value "2" is not set till the end of the constructor (for example).
Probably the Singleton needs to be split into 2, one which delivers the early static data (e.g. 2).
The second which delivers the held object Stuff. Stuff would only rely on the first, which would break the deadlock.
Alternatively, a second constructor to Stuff which told it which object to use, and was called from the Singleton::Singleton
The MSDN article to disable "Magic Statics" MSDN : disable threadsafe static initialization
this is my first time here...
I'm trying to uses multithreaded C++ code.
I'm on a Mac OSX 10.7.2.
Because the OS and compiler are so old and don't support c++11,
I followed the instructions here
https://solarianprogrammer.com/2013/06/11/compiling-gcc-mac-os-x/
I seem to have a working gcc 4.9.1, but then I tried doing some
multi-threading.
#include <thread>
using namespace std;
class X {
public:
char *p;
X() : p(0) { }
~X() { if (p) delete[] p; }
void set(int n) { p = new char[n]; }
};
void task()
{
static thread_local X x;
x.set(8*23);
}
int main()
{
thread t1(task);
thread t2(task);
thread t3(task);
thread t4(task);
thread t5(task);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
}
Well, if I compile this as
/usr/gcc-4.9.1/bin/g++-4.9.1 -g -std=c++11 simple.c
I get errors like this:
a.out(50392,0x100605000) malloc: * error for object 0x137fe130400db0: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Illegal instruction: 4
a.out(50405,0x102a70000) malloc: * error for object 0x137fcf22500060: pointer being freed was not allocated
* set a breakpoint in malloc_error_break to debug
Illegal instruction: 4
I tried adding -pthread and -lpthread as command-line options, but that didn't help.
I added print statement too, which revealed that the addresses in the error messages were the addresses of the static local objects themselves.
Maybe I'm trying to run this in an environment that is just too out of date.
Or maybe the right runtime is not getting linked in.
I'm not sure if anyone out there can help...maybe I just need to get access to
a more up-to-date system.
Thanks!!
I have code similar to below. The code below gives SIGSEGV and points to list::push_back. Is this the right way to use list of boost threads?
struct mythread{
static void myfunc() {
while(1){ }
}
};
int f(){
std::list<boost::thread *> pool;
pool.push_back(new boost::thread(mythread::myfunc));
}
Environment: gcc 4.4.5 on Ubuntu, linked with libboost_thread.a and -lpthread. I am not using c++0x flag.
Regards,
Chubsdad
Note 2: I also get SIGSEGV for the code
pool.push_back(new boost::thread(NULL);
Try taking the address of the function pointer:
pool.push_back(new boost::thread(&mythread::myfunc));