Click to See Complete Forum and Search --> : Invalid pState


Carlos Martinez
March 7th, 2006, 01:29 PM
Hi all:

I'm new to threads and I have a problem with code inside a function executed in a thread (with AfxBeginThread). The same function called normally executes correctly.

Debugging the code I have seen that when execute Accept on a CAsyncSocket object, internally executes a AfxGetThreadState.
The state returned is valid in a normal call, but invalid with threads (invoking that function with AfxBeginThread).
I can't understand that behavior.

Does anybody knows why?

MikeAThon
March 7th, 2006, 03:27 PM
In MFC, you cannot pass a CAsyncSocket object to another thread.

See this and visit the links inside it: http://www.codeguru.com/forum/showthread.php?t=377457

Also, CAsyncSocket will not work asynchronously within a pure worker thread since there's no message pump. You will need a UI thread, or another socket architecture (like event-based sockets, which is not an MFC class).

Mike

Carlos Martinez
March 8th, 2006, 03:52 AM
I don't think the message pump is the cause of error. It seems some "thread state" it's not ok.

Here is the code executed where the error is:

state = sockServ->Accept(*sockRecv);

Inside Accept call:

BOOL CAsyncSocket::Accept(CAsyncSocket& rConnectedSocket,
SOCKADDR* lpSockAddr, int* lpSockAddrLen)
{
ASSERT(rConnectedSocket.m_hSocket == INVALID_SOCKET);
ASSERT(CAsyncSocket::FromHandle(INVALID_SOCKET) == NULL);
...

Inside FromHandle:

_AFXSOCK_INLINE CAsyncSocket* PASCAL CAsyncSocket::FromHandle(SOCKET
hSocket)
{ return CAsyncSocket::LookupHandle(hSocket, FALSE); }

Inside LookupHandle:

CAsyncSocket* PASCAL CAsyncSocket::LookupHandle(SOCKET hSocket, BOOL bDead)
{
CAsyncSocket* pSocket;
_AFX_SOCK_THREAD_STATE* pState = _afxSockThreadState;
if (!bDead)
{
pSocket = (CAsyncSocket*)
pState->m_pmapSocketHandle->GetValueAt((void*)hSocket);
if (pSocket != NULL)
return pSocket;
}
...


The error is in:
pState->m_pmapSocketHandle->GetValueAt((void*)hSocket);

because pState returned by _afxSockThreadState, is not ok. It's member m_pmapSocketHandle (and other members) is NULL.

I read your post (and the link inside it) and test my code creating a new CSocket in my thread (instead of passing to the thread that was the problem commented in the link), but it has the same error.

My question is why SockThreadState, is not ok in the thread but ok in a simple function?

Thanks in advance.

MikeAThon
March 8th, 2006, 10:43 AM
I don't think the message pump is the cause of error. It seems some "thread state" it's not ok.
I know that the message pump is not the cause of your problem. Yet. The point I was trying to make is that after you resolve your current problem, you will not be able to get CAsyncSocket to work asynchronously inside a pure worker thread, since a pure worker thread does not have the message pump that asynchronous sockets rely on.

...The error is in:
pState->m_pmapSocketHandle->GetValueAt((void*)hSocket);

because pState returned by _afxSockThreadState, is not ok. It's member m_pmapSocketHandle (and other members) is NULL.

I read your post (and the link inside it) and test my code creating a new CSocket in my thread (instead of passing to the thread that was the problem commented in the link), but it has the same error.

My question is why SockThreadState, is not ok in the thread but ok in a simple function?

Thanks in advance.
Again, it's because you cannot access a CAsyncSocket object across threads.

The LookupHandle function is fundamental to MFC's process for converting a handle (like a SOCKET handle or a HWND handle) to a C++ object. The function fails when trying to get the CAsyncSocket object associated with a SOCKET handle created in another thread.

In your case, although the client socket might be created inside the thread, the server probably is not. Thus, the function fails at sockserv->Accept, since it can't get the SOCKET handle for the server socket.

Mike

Carlos Martinez
March 8th, 2006, 11:35 AM
In your case, although the client socket might be created inside the thread, the server probably is not. Thus, the function fails at sockserv->Accept, since it can't get the SOCKET handle for the server socket.

Mike

sockserv was originally created inside the main thread, but now is created within the new thread, just before sockrecv.

I don't know the reason, but it doesn't works.
I change my code without threads, using events of CAsyncSocket (OnAccept, OnReceive, ...), and I'm testing the new code.

Thanks for your help.

MikeAThon
March 8th, 2006, 01:59 PM
...I don't know the reason, but it doesn't works.
I change my code without threads, using events of CAsyncSocket (OnAccept, OnReceive, ...), and I'm testing the new code.

Thanks for your help.

Hi Carlos,

Please describe what "doesn't work", so we can help you better. Are you still getting an error concerning pState, or has that now been resolved? Have you abandoned the multi-threaded architecture, to concentrate on your changed code without threads? Are you getting an error in your new single-threaded architecture, or still in the multi-threaded architecture?

In other words, what is it that "doesn't work"?

Best regards,
Mike

Carlos Martinez
March 8th, 2006, 07:01 PM
Hi Carlos,

Please describe what "doesn't work", so we can help you better. Are you still getting an error concerning pState, or has that now been resolved? Have you abandoned the multi-threaded architecture, to concentrate on your changed code without threads? Are you getting an error in your new single-threaded architecture, or still in the multi-threaded architecture?

In other words, what is it that "doesn't work"?

Best regards,
Mike

Hi Mike:

The error persists, and is the same.
Some pointers of pState (obtained from GetSockThreadState) are NULL.
I´m concentrating on changing code without threads (i have a preliminary version that works), because I need the program running in a few days. Perhaps later, I'll try to get it with the multi-threaded architecture.

With single-threaded architecture works.
If I call MyFunction with AfxBeginThread it doesn't work, but if I call directly MyFunction it works.

Now I'll finish the single-threaded version and later, I'll try with threads (perhaps deriving from CWinThread)

Thanks