Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to catch std::invalid_argument

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?

like image 572
laura Avatar asked Apr 28 '26 04:04

laura


2 Answers

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:

-mthreads

Support thread-safe exception handling on 'Mingw32'. Code that relies on thread-safe exception handling must compile and link all code with the -mthreads option. When compiling, -mthreads defines -D_MT; when linking, it links in a special thread helper library -lmingwthrd which cleans up per thread exception handling data.

Please try that before resorting to writing your own thread-safe exceptions.

like image 173
Rob Kennedy Avatar answered Apr 29 '26 16:04

Rob Kennedy


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

like image 38
laura Avatar answered Apr 29 '26 17:04

laura