0

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;
   }
1
Contributor
1
Reply
2
Views
8 Years
Discussion Span
Last Post by dougy83
0

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.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.