CreateThread question

this is a dll callback function which sends details back to mirc about the email

int WINAPI GetEmailInfo(HWND, HWND, char *data, char *parms, BOOL, BOOL)
{
char params[512];
strcpy(params, data);

CreateThread(NULL, 0, Test_Thread, data, 0, 0);
return 3;
}

would the thread then be something like this?

DWORD WINAPI Test_Thread(LPVOID data)
{
//perform socket functions, get email info and send back to mIRC
return 1;
}

if i check up to 50 emails, will that be 50 threads? 1 thread per call?
does my code seem correct?

I used to use standard block sockets with no threads for this, but i had problems on connect() when checking up to 60 emails. thats why im going to try and make the sockets work inside a thread for each call, so am i doing it right?
[857 byte] By [pouncer] at [2007-11-20 1:00:19]
# 1 Re: CreateThread question
if i check up to 50 emails, will that be 50 threads? 1 thread per call?Yes, you are right.

However, it is recommended that you check against the return value of CreateThread to check against thread creation success.
Siddhartha at 2007-11-9 13:59:05 >
# 2 Re: CreateThread question
thans for the reply buddy.

However, it is recommended that you check against the return value of CreateThread to check against thread creation success.

i dont understand wat you mean mate, if the sockets inside the thread connect and recv etc, that thread will have been created successfully so i dnt need to check the return value?
pouncer at 2007-11-9 14:00:05 >
# 3 Re: CreateThread question
if the sockets inside the thread connect and recv etc, that thread will have been created successfully so i dnt need to check the return value?You are making an assumption here.
If the sockets don't connect or transact - it wouldn't mean that the thread creation is not successful - right? ;)

(There can be other reasons too... )

In general, it is important to verify return values of critical APIs for success rather than take them for granted.

Anyways, that was a recommendation as a "best practise". Your software may well work without it, but it will surely work better with it - in event of error.
Siddhartha at 2007-11-9 14:01:05 >
# 4 Re: CreateThread question
ah, good point mate

so do you mean something like

if (CreateThread(NULL, 0, Test_Thread, data, 0, 0) == true)

and have the thread return true/false etc?
pouncer at 2007-11-9 14:02:10 >
# 5 Re: CreateThread question
if (CreateThread(NULL, 0, Test_Thread, data, 0, 0) == true)Something like that - but, not exactly that.

If one reads the documentation, one notices that CreateThread returns a HANDLE and not a BOOL value. ;)

So, a call can be checked for success, like this -
if (CreateThread(NULL, 0, Test_Thread, data, 0, 0) != NULL)
{
// Success...
}
Siddhartha at 2007-11-9 14:03:09 >
# 6 Re: CreateThread question
thanks mate.

is that it thought to check if the createthread was successful? its safe coding practise i assume
pouncer at 2007-11-9 14:04:10 >
# 7 Re: CreateThread question
You are welcome... ;)

Yes, and apart from being safe - one needs the thread HANDLE to do anything meaningful with the thread (like to wait for it, etc).

This HANDLE is returned by CreateThread.
In the code above, we are actually checking that HANDLE against NULL in that "if" statement.
Siddhartha at 2007-11-9 14:05:14 >
# 8 Re: CreateThread question
hey sid. i got a problem when i check 50 emails i get a bad error saying the 'memory cant be read' on memory referencing

the callback function is like this:

int WINAPI Email_Check(HWND, HWND, char *data, char *parms, BOOL, BOOL)
{
char params[512];

sprintf(params, "%s%s", "EMAIL ", data);

if (CheckUpdateInputParams(params) == true)
{

if (CreateThread(NULL, 0, CheckEmail, params, 0, 0) != NULL) { }
}

else
EchoToMirc("Wrong parameters.");

return 1;
}

my thread is like this:

DWORD WINAPI CheckEmail(LPVOID data)
{
int nRet;

string full_data = (char*) data;

vector<string> array = Tokenize(full_data, ' ');
..
..
..
}
pouncer at 2007-11-9 14:06:06 >
# 9 Re: CreateThread question
Visual Studio should take you to the line of code where the crash is occuring...

(BTW, is "data" a null terminated character string? If not, it will cause an access violation.)
Siddhartha at 2007-11-9 14:07:16 >
# 10 Re: CreateThread question
nope its not null terminated, should i use szData ?

it compiles fine, and the way i test this is by generating the .dll and testing it with my mirc

i cant test this any other way
pouncer at 2007-11-9 14:08:17 >
# 11 Re: CreateThread question
nope its not null terminatedSo, that's what caused the problem.
it compiles fine... Compilation success does not guarantee correctness. If a character string buffer is not NULL-terminated, the string classes / functions will not know where to stop and will overrun the buffer.

Why do you copy random data into a string class anyways? Is this for sake of debugging?
In that case, you should use the watch feature of the IDE.
Siddhartha at 2007-11-9 14:09:15 >
# 12 Re: CreateThread question
DWORD WINAPI CheckEmail(LPVOID data)

the data fed into there is from the thread created in the callback function

hmm, should i null terminate the char in the callbac fucntion or the string variable in the thread

im not too sure mate :s
pouncer at 2007-11-9 14:10:13 >
# 13 Re: CreateThread question
hmm, should i null terminate the char in the callbac fucntion or the string variable in the threadIf it is a character string, it is NULL terminated.

However, if you are assigning an object of type T (say a class) to a char* and then using it for string manipulations, you are doing the wrong thing.

What type of object is "data"?
Also, you are still to tell me at what line of code the crash is occuring.
Siddhartha at 2007-11-9 14:11:11 >
# 14 Re: CreateThread question
Note that uninitialized buffers are very dangerous.

i.e. This - char params[512];...Ought to be -
char params[512] = {0};
Siddhartha at 2007-11-9 14:12:16 >
# 15 Re: CreateThread question
ok ive made the {0} change which you mentioned

but i still cant seem to get where it crashes, but i did this

DWORD WINAPI CheckEmail(LPVOID data)
{
int nRet;

string full_data = (char*) data;

MessageBox(0, full_data.c_str(), 0, 0);
..
..

and then i used the callback function from to check 7 emails, it messaged boxed for 4 emails then crashed, so the crash must be somewhere in the callback function :s
pouncer at 2007-11-9 14:13:19 >
# 16 Re: CreateThread question
Pouncer, your Email_Check function returns after creating the thread, the problem is you are passing local variable to thread, and that local variable has no scope after Email_Check returns. You need to eaither wait for some event from the thread which tells you that the data is copied or you should create the params variable on heap using new.

int WINAPI Email_Check(HWND, HWND, char *data, char *parms, BOOL, BOOL)
{
// char params[512];//this is local variable
char * params = new char[512]; // fix it this way.. you need to delete it from the thread.

sprintf(params, "%s%s", "EMAIL ", data);

if (CheckUpdateInputParams(params) == true)
{

if (CreateThread(NULL, 0, CheckEmail, params, 0, 0) != NULL) { }
}

else
EchoToMirc("Wrong parameters.");

return 1;
}

& in thread code..

DWORD WINAPI CheckEmail(LPVOID data)
{
int nRet;

string full_data = (char*) data;
delete data; // to delete the string allocated in Email_check function

vector<string> array = Tokenize(full_data, ' ');
..
..
..
}
Krishnaa at 2007-11-9 14:14:14 >
# 17 Re: CreateThread question
but i still cant seem to get where it crashesThis should be very simple. I hope you are running your application through Visual Studio?

VS will capture the exception and bring you to the line of code.
Siddhartha at 2007-11-9 14:15:22 >
# 18 Re: CreateThread question
Krishnaa - good catch. :thumb:
Siddhartha at 2007-11-9 14:16:17 >
# 19 Re: CreateThread question
Krishnaa - good catch. :thumb:

:cool: :lol:
Krishnaa at 2007-11-9 14:17:26 >
# 20 Re: CreateThread question
kirishna thank you very much buddy i get no crashes now!!

also thanks sidarta for the ongoing help!!
pouncer at 2007-11-9 14:18:28 >
# 21 Re: CreateThread question
hey sid and krishna do you guys use messenger?
pouncer at 2007-11-9 14:19:23 >
# 22 Re: CreateThread question
hey sid and krishna do you guys use messenger?

Why, whats wrong with dev-archive forum ?
Krishnaa at 2007-11-9 14:20:22 >
# 23 Re: CreateThread question
ooh, nothing at all i love dev-archive everyone helps me so much here

was just wandering if i could add you guys as friends but no problem, at all :p

thanks mate!
pouncer at 2007-11-9 14:21:24 >
# 24 Re: CreateThread question
Nice catch on a classic threading error: Assuming that a stack variable will still be there when the thread starts executing ;)

Can't give you points Krishnaa (must "spread them around" first).

Mike
MikeAThon at 2007-11-9 14:22:24 >
# 25 Re: CreateThread question
Can't give you points Krishnaa (must "spread them around" first).No worries, I gave them to him.
Arjay at 2007-11-9 14:23:28 >
# 26 Re: CreateThread question
if i check up to 50 emails, will that be 50 threads? 1 thread per call?
does my code seem correct?

I used to use standard block sockets with no threads for this, but i had problems on connect() when checking up to 60 emails. thats why im going to try and make the sockets work inside a thread for each call, so am i doing it right?

In your code, yes, there would be 50 threads. Every time CreateThread is called, or _beginthreadex(), or beginthread(), or whatever thread spawner function you like, a new thread is created.

In my opinion your sockets thread logic is good, but why make the sockets non-blocking if you are doing it multi-threaded? You'll have to manage the non-blocking syncs _and_ the threading too. If you use blocking sockets (the default), you just worry about the threads. Easy.

-Greg Dolley
greg_dolley at 2007-11-9 14:24:28 >