Sign in to follow this  
Sync Views

Prgram locking up completly

Recommended Posts

Sync Views    139
I know it has something to do wi the CMD_CREATEUSER (no crash without it) and the main/net threads but with it locking my computer up everytime and many of the commands being a few thousand lines (I got board stepping through one of the mysql functions after half an hour in the end) I'm not sure how to debug I cannot see anything in my code that would lock my computer up completly...I can't even get the task manager up to close vs and my program... Net.cpp
...
#define REP_USERCREATE 0x02
struct CommandData
{
	//this is the users session id, 0 is the "public" user and is highly limited
	unsigned long SessionId;
	//this isn't changed by the server so is the same in the reply. 
	//Can be used to detect the reply to this command
	unsigned char Id;
	//the command
	unsigned char Cmd;
	//command data
	std::list<unsigned char> Data;
	//the ip this command came from
	std::string ip;
};
...
void CommandAdd(HANDLE &HCommand, CommandData* Command);//use this to add new commands to the stack (thread safe)
ReplyData* ReplyGet(HANDLE &HReply);//use this to get the next reply. Returns NULL if there are no waiting replys (thread safe)


HANDLE NetHCommand, NetHReply;
bool NetRun=true, NetExit=false;
unsigned int __stdcall NetMain(void* Params)
{
	CreateSemaphores(NetHCommand, NetHReply);
//test user create
	CommandData* Cmd = new CommandData;
	Cmd->ip = "192.168.1.6:3197";
	Cmd->Cmd = CMD_USERCREATE;
	Cmd->SessionId = 0x00000000;
	Cmd->Id = 0x00;
	Cmd->Data.push_back('F');
	Cmd->Data.push_back('i');
	Cmd->Data.push_back('r');
	Cmd->Data.push_back('e');
	Cmd->Data.push_back(' ');
	Cmd->Data.push_back('L');
	Cmd->Data.push_back('a');
	Cmd->Data.push_back('n');
	Cmd->Data.push_back('c');
	Cmd->Data.push_back('e');
	Cmd->Data.push_back('r');
	Cmd->Data.push_back('\0');
	Cmd->Data.push_back('e');
	Cmd->Data.push_back('n');
	Cmd->Data.push_back('r');
	Cmd->Data.push_back('y');
	Cmd->Data.push_back('p');
	Cmd->Data.push_back('t');
	Cmd->Data.push_back('\0');
	Cmd->Data.push_back('D');
	Cmd->Data.push_back('r');
	Cmd->Data.push_back('a');
	Cmd->Data.push_back('g');
	Cmd->Data.push_back('o');
	Cmd->Data.push_back('n');
	Cmd->Data.push_back('_');
	Cmd->Data.push_back('F');
	Cmd->Data.push_back('l');
	Cmd->Data.push_back('y');
	Cmd->Data.push_back('1');
	Cmd->Data.push_back('1');
	Cmd->Data.push_back('0');
	Cmd->Data.push_back('2');
	Cmd->Data.push_back('@');
	Cmd->Data.push_back('h');
	Cmd->Data.push_back('o');
	Cmd->Data.push_back('t');
	Cmd->Data.push_back('m');
	Cmd->Data.push_back('a');
	Cmd->Data.push_back('i');
	Cmd->Data.push_back('l');
	Cmd->Data.push_back('.');
	Cmd->Data.push_back('c');
	Cmd->Data.push_back('o');
	Cmd->Data.push_back('m');
	Cmd->Data.push_back('\0');
	CommandAdd(NetHCommand, Cmd);

	while(NetRun)//the server sets this to false on shutdown
	{
		Sleep(100);
	}
	NetExit = true;
	_endthreadex(0);
	return 0;
}

Command.cpp
#include "command.h"
std::list<CommandData*> CommandsQueue;
std::list<CommandData*> CommandsDone;
std::list<ReplyData*> ReplyQueue;
CommandData* Command;

void CreateSemaphores(HANDLE &HCommand, HANDLE &HReply)
{
	HCommand = NULL;
	while(!HCommand)HCommand = CreateMutex(NULL, FALSE, "SYNC_COMMAND");
	HReply   = NULL;
	while(!HReply)  HReply   = CreateMutex(NULL, FALSE, "SYNC_REPLY");
}

bool CommandNext(HANDLE &HCommand)
{
	while(WaitForSingleObject(HCommand, 10000)==WAIT_TIMEOUT);
	if(CommandsQueue.empty())
	{
		Command = NULL;
		ReleaseMutex(HCommand);
		return false;
	}
	Command = CommandsQueue.front();
	CommandsQueue.pop_front();
	ReleaseMutex(HCommand);
	return true;
}
void CommandDone(HANDLE &HCommand)
{
	while(WaitForSingleObject(HCommand, 10000)==WAIT_TIMEOUT);
	CommandsDone.push_back(Command);
	Command = NULL;
	ReleaseMutex(HCommand);
}
void CommandAdd(HANDLE &HCommand, CommandData* Command)
{
	while(WaitForSingleObject(HCommand, 10000)==WAIT_TIMEOUT);
	CommandsQueue.push_back(Command);
	ReleaseMutex(HCommand);
}
ReplyData* ReplyGet(HANDLE &HReply)
{
	while(WaitForSingleObject(HReply, 10000)==WAIT_TIMEOUT);
	ReplyData* Reply = ReplyQueue.front();
	ReplyQueue.pop_front();
	ReleaseMutex(HReply);
	return Reply;
}
void ReplyAdd(HANDLE &HReply, ReplyData* Reply)
{
	while(WaitForSingleObject(HReply, 10000)==WAIT_TIMEOUT);
	ReplyQueue.push_back(Reply);
	ReleaseMutex(HReply);
}

main.cpp
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	//create log file
	Buffer << "logs\\log_" << time(NULL) << ".txt";
	Log.open(Buffer.str().c_str());
	Log << "Server started at: " << StringTime(time(NULL)) << std::endl;
	//create sync samaphores
	CreateSemaphores(MainHCommand, MainHReply);
	//connect to server
	if(SqlConnect()) Log << "Connected to mysql server" << std::endl;
	else
	{
		Log << "Fatal Error-Failed to connect to mysql server" << std::endl;
		return 0;
	}		
	//create gui thread
	unsigned int GuiId;
	uintptr_t GuiThread = _beginthreadex(
		NULL,
		0,
		GuiMain,
		(void*)hInstance,
		0,
		&GuiId);
	unsigned int NetId;
	//create net thread
	uintptr_t NetThread = _beginthreadex(
		NULL,
		0,
		NetMain,
		NULL,
		0,
		&NetId);

	unsigned long GuiLastUpdate = GetTickCount();
	while(MainRun)
	{
		if(GuiLastUpdate+500 < GetTickCount())
		{
			GuiLastUpdate = GetTickCount();
			InvalidateRect(GuiHwnd, NULL, true);
		}
		//if there is no command wait untill there is one
		if(CommandNext(MainHCommand))
		{
			//log before loggin any replys
			Log << StringCommand(Command) << std::endl;
			//process command
			switch(Command->Cmd)
			{
			case CMD_EXIT:
				{
					MainRun = false;
					NetRun  = false;
					GuiRun  = false;
					break;
				}
			case CMD_LOGIN:
				{
...
				}
			case CMD_USERCREATE:
				{
					std::string User, Pass, Email;
					std::list<unsigned char>::iterator it = Command->Data.begin();
					while(*it != 0x00)
					{
						User += (char)*it;
						++it;
					}
					++it;//get rid of that last NULL
					while(*it != 0x00)
					{
						Pass += (char)*it;
						++it;
					}
					++it;//get rid of that last NULL
					while(*it != 0x00)
					{
						Email += (char)*it;
						++it;
					}

					unsigned char Result = UserCreate(User, Pass, Email);

					ReplyData* Reply = new ReplyData;
					Reply->Cmd = REP_USERCREATE;
					Reply->ip = Command->ip;
					Reply->Id = Command->Id;
					Reply->Data.push_back(Result);
					Log << StringReply(Reply) << std::endl;
					ReplyAdd(MainHReply, Reply);
					break;
				}
			case CMD_LOGOUT:
				{
...
				}
			default:
				{
					break;
				}
			}
			CommandDone(MainHCommand);
		}
		//wait a bit then check if a message has come in
		else Sleep(50);
	}
	while(!GuiExit || !NetExit)Sleep(10);
	return 0;
}

User.cpp
...
int UserCreate(const std::string &Name, const std::string &Pass, const std::string &Email)
{
	if(Name.size() > 32)return 2;

	mysqlpp::StoreQueryResult res;
	std::string str = "SELECT id FROM users WHERE name=\""+Name+"\"";
	res = SendQuery(str);//seems to be here
	if(res.num_rows() > 0)return 1;//user already exists

	str = "SELECT id FROM users WHERE email=\""+Email+"\"";
	res = SendQuery(str);
	if(res.num_rows() > 0)return 3;//email already used

	str = "INSERT INTO users (name, password, email) VALUES(\""+Name+"\",\""+Pass+"\",\""+Email+"\")";
	res = SendQuery(str);
	return 0;
}
...

Sql.cpp
...
#include "mysql++.h"
...
mysqlpp::StoreQueryResult SendQuery(const std::string &Sql)
{
	//query
	mysqlpp::Query query = conn.query(Sql.c_str());
	mysqlpp::StoreQueryResult res = query.store();
	//check for errors
	std::string Error = query.error();
	if(Error=="")return res;
	else  
	{
		MessageBox(NULL, Error.c_str(), "Sql Error", MB_ICONERROR);
		return res;
	}
}
...

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this