DaniWeb IT Discussion Community

DaniWeb IT Discussion Community (http://www.daniweb.com/forums/index.php)
-   C++ (http://www.daniweb.com/forums/forum8.html)
-   -   GCC Exception handling w/ threads (http://www.daniweb.com/forums/thread157968.html)

dougy83 Nov 17th, 2008 11:04 pm
GCC Exception handling w/ threads
 
Hi. I have written a small test socket program that uses a background thread that accepts tcp connections and adds them to a connection list that is accessed by main().

When a connection is opened, then later closed, recv() is called (see line highlighted in code below), which throws an exception stating that the socket is closed.

When I compile in Dev-C++ the exception thrown in the main() thread is caught in the background thread. -- Why is this??

When I compile in Visual Studio 6 the exception is caught in the main() thread as I expected.

I upgraded the Dev-c++ compiler from mingw 3.4.2 to 3.4.5, but the problem still exists.

Does anyone know why this is happening, and if there are any workarounds?

Thanks.

The file is shown following:
Note: the TcpServerSocket.accept() method returns a new open TcpClientObject. All member functions simply call a socket function using the handle stored in the object. Exceptions thrown are derived from std::exception, with what() implemented.
The 2 socket classes are in separate files included in the project during compilation.
#include <cstdlib>
#include <iostream>
#include <string>
#include <list>
#include <conio.h>
#include <stdio.h>

#include "../WindowsPorts/TcpClientSocket.h"
#include "../WindowsPorts/TcpServerSocket.h"

using namespace std;

list<TcpClientSocket*> skts;
bool abortProgram = false;

DWORD __stdcall acceptThread(void *_port){
  int port = *(int*)_port;
  try{
      cout << "Listening on " << port << endl;
      TcpServerSocket listenSocket(port);

      while(1){
        TcpClientSocket *acc = NULL;
       
        try{
            acc = listenSocket.accept();
            }
        catch(exception &x){
            cout << "acceptThread" << " (inner loop) Caught Exception: " << x.what() << endl;
            }

        if(acc){
            cout << "Accepted connection from " << acc->getHost() << ":" << acc->getPort() << endl;
            skts.push_back(acc);
            }

        Sleep(1);      // useless
        }
      }
  catch(exception &x){
      cout << "acceptThread" << " Caught Exception: " << x.what() << endl;
      cout << "Listening Port Closed. Quitting Thread." << endl;
      cin.get();
      abortProgram = true;
      Sleep(10000);
      }

  return 0;
  }

int main(int argc, char *argv[]){
  DWORD port = 12350;
  if(argc == 2){
      port = atoi(argv[1]);
      }
     
  try{
     
      CreateThread(0, 0, acceptThread, &port, 0, 0);

      TcpServerSocket listen(12300);

      list<TcpClientSocket*>::iterator socketInUse = skts.begin();

      while(!abortProgram){
        Sleep(1);
        char ch = 0;

        if(kbhit()){
            ch = getch();
            if(ch == 27){
              if(++socketInUse == skts.end()){
                  socketInUse = skts.begin();
                  }

              if(skts.size() > 0 && socketInUse != skts.end()){
                  cout << "Data will be directed to " << (*socketInUse)->getHost() << "                            \r";
                  }
                 
              ch = 0;
              }
            else{
              try{
                  if(skts.size() > 0 && socketInUse != skts.end()){
                    (*socketInUse)->send(&ch, 1);
                    }
                  }
              catch(exception &x){
                  cout << "main" << " Caught Exception: " << x.what() << endl;
                  }
              }
            }

        for(list<TcpClientSocket*>::iterator it = skts.begin(); it != skts.end(); it++){
            try{
              if((*it)->waitForData(10) == 1){    // got data, display it
                  char buff[1500];
// ########### the following line will throw the exception when the connection is closed (remotely)
                  unsigned int len = (*it)->recv(buff, sizeof(buff));

//                  cout << "read " << len << " bytes " << (len == 0) << endl;
                  if(len > 0) 
                    cout << (*it)->getHost() << ": " << string(buff, len) << endl;
                  }
              }
            catch(exception &x){
              cout << "main" << " Caught Exception: " << x.what() << endl;
              cout << "Closing port" << endl;

                              bool reset = false;
              if(socketInUse == it){
                  reset = true;
                  }

              delete *it;      // destroy object
              skts.erase(it);  // destroy reference

                              if(reset)
                  socketInUse = skts.end();

              break;
              }
            catch(...){
              cout << "main" << " Unhandled Exception" << endl;
              cout << "Closing port" << endl;

                              bool reset = false;
                                if(socketInUse == it){
                  reset = true;
                  }

              delete *it;      // destroy object
              skts.erase(it);  // destroy reference
             
              if(reset)
                  socketInUse = skts.end();

              break;
              }
            }
        }
      }
  catch(exception &x){
      cout << "main" << " Caught Exception: " << x.what() << endl;
      }
  catch(...){
      cout << "main" << " Unhandled Exception" << endl;
      }

  system("PAUSE");
  return EXIT_SUCCESS;
  }

dougy83 Nov 18th, 2008 12:40 am
Re: GCC Exception handling w/ threads
 
OK, I found out the compilation option -mthreads (MinGW specific) is needed to allow safe threaded code with exceptions. It may also be the case that -pthreads is required for non-MinGW gcc.


All times are GMT -4. The time now is 6:53 pm.

Forum system based on vBulletin Copyright ©2000 - 2009, Jelsoft Enterprises Ltd.
©2003 - 2009 DaniWeb® LLC