I've run into an issue catching a std::invalid_argument exception that I'm not able to trace. I'm using gcc 4.4.0 (windows), pthreads-win32 2.8.0 the GC2 dll.
Basically, from two threads (main thread and a thread started using pthread_create), I try to create an instance of class A at roughly the same time. The constructor throws an std::invalid_argument, but it is surrounded by try/catch blocks which should catch the exception. However, that does not happen (very rarely, only one of the threads might catch the exception - no rule as to which will do it though)
If I attempt to create the object on only one of the threads, the create works as it should, and the exception is caught. If I create the two objects at different times, the create works as it should and the exception is caught. If I try to create them at the same time, ::terminate() gets called.
Maybe someone has an idea of why this happens (I've excluded headers):
void *run(void *ptr)
{
Sleep(5000);
try
{
A *a = new A(5);
a->a = 12;
}
catch (std::exception &ex)
{
printf("t - %s\n", ex.what());
}
return NULL;
}
int main(void) {
pthread_t t;
if (pthread_create(&t, NULL, run, NULL) != 0)
{
printf("No thread\n");
}
else
{
Sleep(5000);
try
{
A *a = new A(5);
a->a = 13;
} catch (std::exception &ex)
{
printf("M - %s\n", ex.what());
}
pthread_join(t, NULL);
}
return 0;
}
class A
{
public:
A(int a);
virtual ~A();
int a;
};
A::A(int a)
{
throw std::invalid_argument("Invalid!");
}
A::~A(){}
The makefile is:
CXXFLAGS = -O0 -g -Wall -Werror -fmessage-length=0
OBJS = WOpenTest.o A.o
INCL = -I../pthreads-win32/include
LIBS = -lws2_32 -lgdi32 -lpthreadGC2
LIB_DIRS = -L ../pthreads-win32/lib
TARGET = WOpenTest.exe
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS) $(LIB_DIRS) $(INCL)
WOpenTest.o : WOpenTest.cpp
g++ $(CXXFLAGS) -c WOpenTest.cpp $(INCL)
A.o : A.cpp A.h
g++ $(CXXFLAGS) -c A.cpp $(INCL)
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
The output I am seeing is:
(Most frequently) $ ./WOpenTest.exe
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. terminate called after throwing an instance of 'std::invalid_argument' terminate called recursively
or
$ ./WOpenTest.exe
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. M - Invalid!
or
$ ./WOpenTest.exe
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. t - Invalid!
or
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information.
This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. terminate called after throwing an instance of 'std::invalid_argument'
what(): Invalid!
Any ideas on what I should be doing and I'm not? Or something I'm missing with pthreads?
You have concluded that this is connected with the single-threaded libraries that MinGW links to. I found a page about configuring NetBeans to use MinGW, and it has the following advice under the "Multithreading with Posix threads" section:
- Important if using exception handling: Compile your application with the additional compiler switch "-mthreads". Otherwise exception handling will not work reliable and unspecific crashes may occur. Other problems may arise while propagating exceptions out of a DLL into an application. I have found some hints concerning this in the net, but have no experience with it because my DLL does not throw exceptions.
It's also described in the GCC documentation for x86 options:
-mthreadsSupport thread-safe exception handling on '
Mingw32'. Code that relies on thread-safe exception handling must compile and link all code with the-mthreadsoption. When compiling,-mthreadsdefines-D_MT; when linking, it links in a special thread helper library-lmingwthrdwhich cleans up per thread exception handling data.
Please try that before resorting to writing your own thread-safe exceptions.
Posting final answer here in case someone looks for it in the future. The issue is a critical bug in gcc 4.4:
http://n2.nabble.com/gcc-4-4-multi-threaded-exception-handling-thread-specifier-not-working-td3440749.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With