GCC Exception handling w/ threads

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Jun 2007
Posts: 275
Reputation: dougy83 is on a distinguished road 
Solved Threads: 45
dougy83 dougy83 is offline Offline
Posting Whiz in Training

GCC Exception handling w/ threads

 
0
  #1
Nov 17th, 2008
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.
  1. #include <cstdlib>
  2. #include <iostream>
  3. #include <string>
  4. #include <list>
  5. #include <conio.h>
  6. #include <stdio.h>
  7.  
  8. #include "../WindowsPorts/TcpClientSocket.h"
  9. #include "../WindowsPorts/TcpServerSocket.h"
  10.  
  11. using namespace std;
  12.  
  13. list<TcpClientSocket*> skts;
  14. bool abortProgram = false;
  15.  
  16. DWORD __stdcall acceptThread(void *_port){
  17. int port = *(int*)_port;
  18. try{
  19. cout << "Listening on " << port << endl;
  20. TcpServerSocket listenSocket(port);
  21.  
  22. while(1){
  23. TcpClientSocket *acc = NULL;
  24.  
  25. try{
  26. acc = listenSocket.accept();
  27. }
  28. catch(exception &x){
  29. cout << "acceptThread" << " (inner loop) Caught Exception: " << x.what() << endl;
  30. }
  31.  
  32. if(acc){
  33. cout << "Accepted connection from " << acc->getHost() << ":" << acc->getPort() << endl;
  34. skts.push_back(acc);
  35. }
  36.  
  37. Sleep(1); // useless
  38. }
  39. }
  40. catch(exception &x){
  41. cout << "acceptThread" << " Caught Exception: " << x.what() << endl;
  42. cout << "Listening Port Closed. Quitting Thread." << endl;
  43. cin.get();
  44. abortProgram = true;
  45. Sleep(10000);
  46. }
  47.  
  48. return 0;
  49. }
  50.  
  51. int main(int argc, char *argv[]){
  52. DWORD port = 12350;
  53. if(argc == 2){
  54. port = atoi(argv[1]);
  55. }
  56.  
  57. try{
  58.  
  59. CreateThread(0, 0, acceptThread, &port, 0, 0);
  60.  
  61. TcpServerSocket listen(12300);
  62.  
  63. list<TcpClientSocket*>::iterator socketInUse = skts.begin();
  64.  
  65. while(!abortProgram){
  66. Sleep(1);
  67. char ch = 0;
  68.  
  69. if(kbhit()){
  70. ch = getch();
  71. if(ch == 27){
  72. if(++socketInUse == skts.end()){
  73. socketInUse = skts.begin();
  74. }
  75.  
  76. if(skts.size() > 0 && socketInUse != skts.end()){
  77. cout << "Data will be directed to " << (*socketInUse)->getHost() << " \r";
  78. }
  79.  
  80. ch = 0;
  81. }
  82. else{
  83. try{
  84. if(skts.size() > 0 && socketInUse != skts.end()){
  85. (*socketInUse)->send(&ch, 1);
  86. }
  87. }
  88. catch(exception &x){
  89. cout << "main" << " Caught Exception: " << x.what() << endl;
  90. }
  91. }
  92. }
  93.  
  94. for(list<TcpClientSocket*>::iterator it = skts.begin(); it != skts.end(); it++){
  95. try{
  96. if((*it)->waitForData(10) == 1){ // got data, display it
  97. char buff[1500];
  98. // ########### the following line will throw the exception when the connection is closed (remotely)
  99. unsigned int len = (*it)->recv(buff, sizeof(buff));
  100.  
  101. // cout << "read " << len << " bytes " << (len == 0) << endl;
  102. if(len > 0)
  103. cout << (*it)->getHost() << ": " << string(buff, len) << endl;
  104. }
  105. }
  106. catch(exception &x){
  107. cout << "main" << " Caught Exception: " << x.what() << endl;
  108. cout << "Closing port" << endl;
  109.  
  110. bool reset = false;
  111. if(socketInUse == it){
  112. reset = true;
  113. }
  114.  
  115. delete *it; // destroy object
  116. skts.erase(it); // destroy reference
  117.  
  118. if(reset)
  119. socketInUse = skts.end();
  120.  
  121. break;
  122. }
  123. catch(...){
  124. cout << "main" << " Unhandled Exception" << endl;
  125. cout << "Closing port" << endl;
  126.  
  127. bool reset = false;
  128. if(socketInUse == it){
  129. reset = true;
  130. }
  131.  
  132. delete *it; // destroy object
  133. skts.erase(it); // destroy reference
  134.  
  135. if(reset)
  136. socketInUse = skts.end();
  137.  
  138. break;
  139. }
  140. }
  141. }
  142. }
  143. catch(exception &x){
  144. cout << "main" << " Caught Exception: " << x.what() << endl;
  145. }
  146. catch(...){
  147. cout << "main" << " Unhandled Exception" << endl;
  148. }
  149.  
  150. system("PAUSE");
  151. return EXIT_SUCCESS;
  152. }
Reply With Quote Quick reply to this message  
Join Date: Jun 2007
Posts: 275
Reputation: dougy83 is on a distinguished road 
Solved Threads: 45
dougy83 dougy83 is offline Offline
Posting Whiz in Training

Re: GCC Exception handling w/ threads

 
0
  #2
Nov 18th, 2008
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.
Last edited by dougy83; Nov 18th, 2008 at 12:42 am.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC