Access violation reading location while using CSocket across threads....

Maverick_Cool
Maverick_Cool used Ask the Experts™
on
I am modify a VC++ web server code(small),
It throws access violation in sockcore.cpp while starting a new threading, Myapp is non  mfc, but i have headers file to access CString and CSocket.

Is there a solution.
I am posting my code.
#include "stdafx.h"
#include <atlstr.h>
 
//process.h
#include <afxsock.h>
 
 
 
CString Path;
UINT NewThread (LPVOID p);
CString MIME(CString GetEX);
 
int Connections;
bool doRun = true;
CSocket Listener;
 
void webserver()
{
char TPath[50];
		//cout << "Enter the path to your index file" << endl;
		//cout << "Ex: C:\\html\\MicahServer" << endl;
		//cin >> TPath;
		//Path.Format("%s", &TPath);
Path = "c:\\webserver\\root";
		AfxSocketInit();
		//CSocket Listener;
		
		int Code = Listener.Create(80); //Create socket
		if( Code == 0 ) 
		{
//			cout << "Error creating Socket." << endl; //Get this usually if something is already listening on Port 80.
			
		}
 
		Listener.Listen();
		//cout << "Listening..." << endl;
		
		while(1)
		{
 
			CSocket pConn;
			Listener.Accept(pConn); //Accept on pConn.
			Connections++;
			AfxBeginThread(NewThread, (LPVOID) pConn.Detach()); //Start new thread.
				
		}
 
}
 
 
UINT NewThread (LPVOID p)
 
{
	CSocket TheConn;
	TheConn.Attach((SOCKET)p);
 
	
	CSocketFile file(&TheConn);
	CArchive arIn(&file, CArchive::load);
	CArchive arOut(&file, CArchive::store);
	CString Request;
	CString RFile;
 
	int First = 0;
	do {
		arIn.ReadString(Request); //Read incomming data line by line.
		//cout << (LPCTSTR)Request << endl;
		if (First == 0 ){
			RFile = Request.Mid(4, Request.Find(L" ", 4) - 4);
			First = 1;
		}
	} while (Request != "");
 
 
	CString Temp;
	CString Type;
	CString GetEX;
	CString HisIP;
	CString Varis;
	unsigned int Port;
	
	TheConn.GetPeerName(HisIP, Port); //Get Clients IP and Port.
 
//	cout << endl << "Connected to " << (LPCSTR)HisIP <<", on port " << Port << endl;
 
	
	GetEX = RFile.Mid(RFile.Find(L".", 1) + 1);
 
	if( GetEX.Find(L"?",1)!=-1){ // Remove any variables the Client tried to send in the request
		Varis = GetEX.Mid(GetEX.Find(L"?",1) +1);
		GetEX = GetEX.Mid(0, GetEX.Find(L"?"));
		RFile = RFile.Mid(0, RFile.Find(L"?"));
 
	}
 
	Type.Format(MIME(GetEX)); // Get the MIME Type
 
	
	if( RFile == "/" ) { //If only recived a / look for index file.
		CFile Filer;
		CString TFile;
		CFileException peError;
		RFile.Format(L"\\index.html");
		TFile.Format(L"%s%s",Path, RFile); 
 
		if (!Filer.Open(TFile, CFile::shareDenyNone, &peError)){
			RFile.Format(L"\\index.php");
			TFile.Format(L"%s%s",Path, RFile); 
			
			if (!Filer.Open(TFile, CFile::shareDenyNone, &peError)){
				RFile.Format(L"\\index.htm");
				TFile.Format(L"%s%s",Path, RFile); 
				
				if (!Filer.Open(TFile, CFile::shareDenyNone, &peError)){
					RFile.Format(L"\\index.htm");
					TFile.Format(L"%s%s",Path, RFile); 
				}
			}
		}
	}
	
	
	Temp.Format(L"%s", (LPCSTR)(LPCTSTR)RFile);
	RFile.Format(L"%s%s", Path, Temp);
 
//	cout << (LPCSTR)RFile << " " << (LPCSTR)Type << endl;
	
	CString AllData;
 
	int FLen;
	char *FileData[8193];
	CFile File;
	CFileException pError;
 
	if (File.Open(RFile, CFile::shareDenyNone, &pError))
	{
		FLen = File.GetLength();
		AllData.Format(L"HTTP/1.1 200 OK\nContent-Type: %s\nServer: TCS MicahServer 4.0a\nContent-Length: %d\nConnection: close\n\n", Type, FLen); //Header
		TheConn.Send(AllData, AllData.GetLength(), 0);
 
		UINT nRead;
		while ((nRead = File.Read(FileData, 8192)))// File.Read returns the number of bytes successfully read.
			TheConn.Send(FileData, nRead, 0); // Send data
	}
	else
	{
		AllData.Format(L"HTTP/1.1 404 Object Not Found\nServer: TCS MicahServer 4.0a\nConnection: close\n\n");
		
		int AllSize;
		AllSize =  AllData.GetLength();	
		
		TheConn.Send(AllData, AllSize, 0); //Send data
	}
 
	return 0;
}
 
CString MIME(CString GetEX)
{
	GetEX.MakeLower();
	if ( GetEX == "gif" ){
		return "image/gif";
	}
	if ( GetEX == "jpg" ){
		return "image/jpeg";
	}
	if ( GetEX == "zip" ){
		return "aplication/zip";
	}
	if ( GetEX == "exe" ){
		return "aplication/exe";
	}
	if ( GetEX == "asp" ){
		return "text/asp";
	}
	if ( GetEX == "bmp" ){
		return "image/bmp";
	}
	if ( GetEX == "mov" ){
		return "video/quicktime";
	}
	if ( GetEX == "mp3" ){
		return "video/mpeg";
	}
	if ( GetEX == "mpeg" ){
		return "video/mpeg";
	}
	if ( GetEX == "txt" ){
		return "text/plain";
	}
	if ( GetEX == "cab" ){
		return "application/octet-stream";
	}
	else {
		return "text/html";
	}
 
}

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
On line 55 above try:


CSocket TheConn;
if(p) {
    SOCKET * _p = (SOCKET)p;
    TheConn.Attach(*_p);
}
else {
    AfxMessageBox(_T("p is NULL"));
}

Open in new window

Author

Commented:
Error    2    error C2440: 'initializing' : cannot convert from 'SOCKET' to 'SOCKET *'  

Sorry, try:
CSocket TheConn;
if(p) {
    SOCKET * _p = (SOCKET*)p;
    TheConn.Attach(*_p);
}
else {
    AfxMessageBox(_T("p is NULL"));
}

Open in new window

CompTIA Network+

Prepare for the CompTIA Network+ exam by learning how to troubleshoot, configure, and manage both wired and wireless networks.

...also on line 44 I believe you need to call it as in the code snippet below. I don't have access to a compiler at the moment so please let me know if it fails and I'll take a look at it tomorrow.
AfxBeginThread(NewThread, (LPVOID)&pConn.Detach());

Open in new window

Author

Commented:
Unhandled exception at 0x00403d40 in xxxxxxxx.exe: 0xC0000005: Access violation reading location 0x00000d84.

Author

Commented:
changing line 44:
Error    1    error C2102: '&' requires l-value    

Ok, sorry for the inconvenience, I will follow up tomorrow.

The problem is the second parameter of the thread function is a void pointer, whereas the Detach function returns a SOCKET structure, if you like try also this also line 44:


SOCKET _s = pConn.Detach();
AfxBeginThread(NewThread, (LPVOID)&_s); 

Open in new window

Author

Commented:
well when is was separate console application it was working properly,
some thing to do with wnd class registration and hooking
Yes, you are correct, something else is causing the problem. Can you provide additional details regarding what type of project it is, i.e. is the project a Win32 console application, a DLL? You already mentioned it is not an MFC application. How do you invoke it? Any other details you can add, e.g. the line where the debug assertions occurs, would also be helpful.
>>>> AfxBeginThread(NewThread, (LPVOID) pConn.Detach()); //Start new thread.

The Detach returns a socket handle. It makes no sense to turning that to a pointer to SOCKET.

The original code correctly made a cast to SOCKET.

>>>> It throws access violation in sockcore.cpp while starting a new threading

I assume you encounter the error in debug mode? If so, could you check the call stack and tell where it crashes in *your* code?

Access violation means pointer error. The prog most probably dies in sockcore.cpp cause you call a socket function using a NULL pointer or a pointer which already was deleted or a pointer which points to local memory which already was freed.

To verify that check all pointers involved when crashing in the debugger especially the 'this'. If this is NULL it is the reason why it crashed.
>>>> char *FileData[8193];

That is an array of char pointers. You were using it in CFile::Read which expects an array of chars (and not an array of pointers). Your code will work nevertheless as you pass the same array to CAsyncSocket::Send which also expects a char buffer. Since a pointer array was bigger in size than a char array the wrong type doesn't harm but all in all it is a rather bad code with poor initializing and risky casts and you will have bad luck if you don't make some fundamental overwork.

>>>>             while(1)
>>>>             {
>>>> 
>>>>                   CSocket pConn;
>>>>                   Listener.Accept(pConn); //Accept on pConn.
>>>>                   Connections++;
>>>>                   AfxBeginThread(NewThread, (LPVOID) pConn.Detach()); //Start new thread.
>>>>                         
>>>>             }

In that loop you create a new CSocket and call Accept. Then, you start a new thread passing the new socket handle. But after that call (and before the new thread could be alive) the loop cycle ends and the CSocket pConn runs out of scope. That means that the destructor was called and the pConn was disconnected. That makes the passed socket handle invalid as well.

You need to define the CSocket before the loop and you MUST have some way how to break the infinite loop somehow (e. g. by accepting a client which invokes a stop request).
 

Author

Commented:
i couldn't make it work...the problem was use of mfc lib filesin non mfc app. CSocket works poorly with threads when its not able find app handler
>>> CSocket works poorly with threads when its not able find app

You can pass a pointer to your app to the thread, e. g. by using a structure like

  struct ThreadData
  {
      SOCKET sock;
      MyApp * ptrApp;
  };

in myapp.cpp

BOOL MyApp::createThreads()
{
     for (int i = 0; i < MAX_THREADS; ++i)
     {
          ThreadData * pt = new ThreadData;
          pt->sock = getSocketForThread(i);
          pt->sock = this;   // here set the application pointer

          HANDLE h = _beginthread(threadFunc, 0, pt);   // create thread and pass ThreadData
         
          // save thread resources
          myThreads.push_back(pair<ThreadData*, HANDLE>(pt, h));          
     }
}

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial