Pthread semaphore TCP - pthreads

I wanna create 2 threads in client, each thread will send a message to server and get rebounce or download a file from server, using TCP protocole. This program run very well when I didn't add pthread in it. After I created 2 threads in client, It doesn't communicate with server. Normally, thread will tell server which operation it wants, then server respond, but when one thread send the message, there is no respond from server, and this thread exit immediately, next thread occupy the semaphore but exit without chose the operation.
Code
void semaphore()
{
int nThread = 2;
int nSemaphore = 1;
int nRet = -1;
pthread_t threadIDs[nThread];
nRet = sem_init(&sem, 0, nSemaphore);
if(nRet == -1)
{
perror("Semaphore intialization failed!!!\n");
exit(EXIT_FAILURE);
}
int i;
for (i = 0; i < nThread; ++i)
{
nRet = pthread_create(&threadIDs[i], NULL, thread, NULL);
if(nRet != 0)
{
perror("pthreas_create failed!!!\n");
exit(EXIT_FAILURE);
}
}
for(i = 0; i < nThread; ++i)
{
nRet = pthread_join(threadIDs[i], NULL);
if(nRet != 0)
{
printf("Threan %d join failed!!!\n", i);
exit(EXIT_FAILURE);
}
}
sem_destroy(&sem);
}
enter code here
void *thread(void* p)
{
pthread_t id = pthread_self();
sem_wait(&sem);
pthread_mutex_lock(&mutex);
int operation ;
//向服务器(特定的IP和端口)发起请求
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr)); //每个字节都用0填充
serv_addr.sin_family = AF_INET; //使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //具体的IP地址
serv_addr.sin_port = htons(1234); //端口
printf("\nThis is client %ld", id);
printf("\nWhich operation do you want:\n");
printf("1:Sending message to server and get rebound\n");
printf("2:Downlown a file from server\n");
scanf("Your chose:%d", &operation);
switch(operation)
{
case 1:
{
sendMessage(serv_addr);
break;
}
case 2:
{
download(serv_addr);
break;
}
default:
break;
}
sem_post(&sem);
pthread_mutex_unlock(&mutex);
}
From terminal
This is client 139671599236864
Which operation do you want:
1:Sending message to server and get rebound
2:Downlown a file from server
Your choise:1
This is client 139671590844160
Which operation do you want:
1:Sending message to server and get rebound
2:Downlown a file from server
Can someone tell me where is the problem?

Related

Create multiple sockets on Berkeley App (Harmony3)

I'm currently working with a pic32 starter kit and i want to use it as a Berkeley server, the code above is an example part of "Harmony 3" and it works, now I'm trying to use two sockets, one for SERVERPORT 9760 and another SERVERPORT2 9650, is this possible?
BSD_APP_DATA berkeleyApp;
bool _APP_BsdChangeNetParam(TCPIP_NET_HANDLE netH);
void APP_BSD_Initialize(void)
{
/* Place the Berkeley App state machine in its initial state. */
berkeleyApp.state = APP_BSD_WAIT_INIT;
berkeleyApp.isDataAvailable = false;
berkeleyApp.isDoneSending = false;
}
void APP_BSD_Tasks()
{
SYS_STATUS tcpipStat;
const char *netName, *netBiosName;
int i, nNets;
TCPIP_NET_HANDLE netH;
switch (berkeleyApp.state)
{
case APP_BSD_WAIT_INIT:
tcpipStat = TCPIP_STACK_Status(sysObj.tcpip);
if (tcpipStat < 0)
{ // some error occurred
SYS_CONSOLE_MESSAGE(" APP BSD: TCP/IP stack initialization failed!\r\n");
berkeleyApp.state = APP_BSD_ERROR;
}
else if (tcpipStat == SYS_STATUS_READY)
{
// now that the stack is ready we can check the
// available interfaces
nNets = TCPIP_STACK_NumberOfNetworksGet();
for (i = 0; i < nNets; i++)
{
netH = TCPIP_STACK_IndexToNet(i);
netName = TCPIP_STACK_NetNameGet(netH);
netBiosName = TCPIP_STACK_NetBIOSName(netH)
}
berkeleyApp.state = APP_BSD_WAIT_FOR_IP;
}
break;
case APP_BSD_WAIT_FOR_IP:
nNets = TCPIP_STACK_NumberOfNetworksGet();
for (i = 0; i < nNets; i++)
{
netH = TCPIP_STACK_IndexToNet(i);
if (!TCPIP_STACK_NetIsReady(netH))
{
return; // interface not ready yet!
}
/* carga de la IP si la configuracion esta lista*/
if (!APP_ConfigStatusGet())
{
return; // No hay datos de configuracion aun
}
if (!_APP_BsdChangeNetParam(netH))
{
berkeleyApp.state = APP_BSD_ERROR;
}
}
// all interfaces ready. Could start transactions!!!
berkeleyApp.state = APP_BSD_INIT;
break;
case APP_BSD_INIT:
// Initialize all client socket handles so that we don't process
// them in the BSD_OPERATION state
/*CLIENT SOCKETS FOR CHANNEL 1*/
for (i = 0; i < MAX_CLIENT; i++)
berkeleyApp.ClientSockCh1[i] = INVALID_SOCKET;
/*CLIENT SOCKETS FOR CHANNEL 2*/
for (i = 0; i < MAX_CLIENT; i++)
berkeleyApp.ClientSockCh2[i] = INVALID_SOCKET;
berkeleyApp.state = APP_BSD_CREATE_SOCKET;
break;
case APP_BSD_CREATE_SOCKET:
{
// Create a socket for this server to listen and accept connections on
/*SOCKET FOR CHANNEL 1*/
SOCKET tcpSkt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcpSkt == INVALID_SOCKET)
return;
berkeleyApp.bsdServerSocketCh1 = (SOCKET) tcpSkt;
SYS_CONSOLE_PRINT("Channel 1 Socket Created %d\r\n",tcpSkt);
/*SOCKET FOR CHANNEL 2*/
SOCKET tcpSkt2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (tcpSkt2 == INVALID_SOCKET)
return;
berkeleyApp.bsdServerSocketCh2 = (SOCKET) tcpSkt2;
SYS_CONSOLE_PRINT("Channel 2 Socket Created %d\r\n",tcpSkt2);
berkeleyApp.state = APP_BSD_BIND;
}
break;
case APP_BSD_BIND:
{
// Bind socket to a local port
/*BIND SOCKET FOR CHANNEL 1 TO LOCAL PORT 9760*/
struct sockaddr_in addr;
int addrlen = sizeof (struct sockaddr_in);
addr.sin_port = SERVER_PORT_CH1;
addr.sin_addr.S_un.S_addr = IP_ADDR_ANY;
int stat = bind(berkeleyApp.bsdServerSocketCh1, (struct sockaddr*) &addr, addrlen);
if ( stat == SOCKET_ERROR)
return;
SYS_CONSOLE_PRINT("Channel 1 Socket Binded %d\r\n",stat);
/*BIND SOCKET FOR CHANNEL 2 TO LOCAL PORT 9650*/
struct sockaddr_in addr2;
int addrlen2 = sizeof (struct sockaddr_in);
addr2.sin_port = SERVER_PORT_CH2;
addr2.sin_addr.S_un.S_addr = IP_ADDR_ANY;
int stat2 = bind(berkeleyApp.bsdServerSocketCh2, (struct sockaddr*) &addr2, addrlen2);
if ( stat2 == SOCKET_ERROR)
return;
SYS_CONSOLE_PRINT("Channel 2 Socket Binded %d\r\n",stat2);
berkeleyApp.state = APP_BSD_LISTEN;
// No break needed
}
break;
case APP_BSD_LISTEN:
{
/*LISTENING FOR CHANNEL 1*/
if (listen(berkeleyApp.bsdServerSocketCh2, MAX_CLIENT) == 0) {
SYS_CONSOLE_PRINT("Waiting for Client Connection on port: %d\r\n", SERVER_PORT_CH2);
}
/*LISTENING FOR CHANNEL 2*/
int algo = listen(berkeleyApp.bsdServerSocketCh1, MAX_CLIENT);
if ( algo == 0) {
SYS_CONSOLE_PRINT("Waiting for Client Connection on port: %d\r\n", SERVER_PORT_CH1);
}
SYS_CONSOLE_PRINT("listen channel 2: %d",algo);
berkeleyApp.state = APP_BSD_OPERATION;
}
break;
case APP_BSD_OPERATION:
{
int length;
struct sockaddr_in addRemote;
int addrlen = sizeof (struct sockaddr_in);
berkeleyApp.isDoneSending = false;
for (i = 0; i < MAX_CLIENT; i++)
{
// Accept any pending connection requests, assuming we have a place to store the socket descriptor
if (berkeleyApp.ClientSockCh1[i] == INVALID_SOCKET)
berkeleyApp.ClientSockCh1[i] = accept(berkeleyApp.bsdServerSocketCh1, (struct sockaddr*) &addRemote, &addrlen);
// If this socket is not connected then no need to process anything
if (berkeleyApp.ClientSockCh1[i] == INVALID_SOCKET)
continue;
// For all connected sockets, receive and send back the data
length = recv(berkeleyApp.ClientSockCh1[i], berkeleyApp.rxBuffer, sizeof (berkeleyApp.rxBuffer), 0);
if (length > 0)
{
berkeleyApp.rxBuffer[length] = '\0';
berkeleyApp.state = APP_BSD_WAIT_USART_RECEIVE_DATA;
berkeleyApp.isDataAvailable = true;
berkeleyApp.channels = CHANNEL1;
berkeleyApp.socket = i;
APP_UsartWriteBuffer(berkeleyApp.rxBuffer);
#ifdef DEBUG
SYS_CONSOLE_PRINT("BklR <%s> <sck:%d>\n\r",berkeleyApp.rxBuffer,berkeleyApp.socket);
#endif
}
else if (length == 0 || errno != EWOULDBLOCK)
{
closesocket(berkeleyApp.ClientSockCh1[i]);
berkeleyApp.ClientSockCh1[i] = INVALID_SOCKET;
}
// else just wait for some more data
}
for (i = 0; i < MAX_CLIENT; i++)
{
// Accept any pending connection requests, assuming we have a place to store the socket descriptor
if (berkeleyApp.ClientSockCh2[i] == INVALID_SOCKET)
berkeleyApp.ClientSockCh2[i] = accept(berkeleyApp.bsdServerSocketCh2, (struct sockaddr*) &addRemote, &addrlen);
// If this socket is not connected then no need to process anything
if (berkeleyApp.ClientSockCh2[i] == INVALID_SOCKET)
continue;
// For all connected sockets, receive and send back the data
length = recv(berkeleyApp.ClientSockCh2[i], berkeleyApp.rxBuffer, sizeof (berkeleyApp.rxBuffer), 0);
if (length > 0)
{
berkeleyApp.rxBuffer[length] = '\0';
berkeleyApp.state = APP_BSD_WAIT_USART_RECEIVE_DATA;
berkeleyApp.isDataAvailable = true;
berkeleyApp.channels = CHANNEL2;
berkeleyApp.socket = i;
APP_UsartWriteBuffer(berkeleyApp.rxBuffer);
#ifdef DEBUG
SYS_CONSOLE_PRINT("BklR <%s> <sck:%d>\n\r",berkeleyApp.rxBuffer,berkeleyApp.socket);
#endif
}
else if (length == 0 || errno != EWOULDBLOCK)
{
closesocket(berkeleyApp.ClientSockCh2[i]);
berkeleyApp.ClientSockCh2[i] = INVALID_SOCKET;
}
// else just wait for some more data
}
// Pregunta por cambios en la configuracion de red
if (APP_ConfigNetChangeGet() || APP_DefaultConfigNetChangeGet())
{
// cierra socket por seguridad solamente
if (berkeleyApp.channels == CHANNEL1)
{
closesocket(berkeleyApp.ClientSockCh1[i]);
berkeleyApp.ClientSockCh1[i] = INVALID_SOCKET;
}
closesocket(berkeleyApp.ClientSockCh2[i]);
berkeleyApp.ClientSockCh2[i] = INVALID_SOCKET;
// limpia banderas de cambio de configuracion y cambia estado para recargar parametros de red
APP_ConfigNetChangeClear();
APP_DefaultConfigNetChangeClear();
netH = TCPIP_STACK_IndexToNet(0);
if (!_APP_BsdChangeNetParam(netH))
{
berkeleyApp.state = APP_BSD_ERROR;
}
}
break;
}
case APP_BSD_WAIT_USART_RECEIVE_DATA:
{
if (APP_UsartTransferStatusGet())
{
#ifdef DEBUG
SYS_CONSOLE_PRINT("BklS <%s> <%d>\n\r", berkeleyApp.txBuffer,strlen(berkeleyApp.txBuffer));
#endif
APP_UsartReadBuffer(berkeleyApp.txBuffer);
if(berkeleyApp.channels == CHANNEL1)
{
send(berkeleyApp.ClientSockCh1[berkeleyApp.socket], berkeleyApp.txBuffer, strlen(berkeleyApp.txBuffer), 0);
}
send(berkeleyApp.ClientSockCh2[berkeleyApp.socket], berkeleyApp.txBuffer, strlen(berkeleyApp.txBuffer), 0);
berkeleyApp.isDoneSending = true;
berkeleyApp.isDataAvailable = false;
berkeleyApp.state = APP_BSD_OPERATION;
}
break;
}
case APP_BSD_ERROR:
break;
default:
break;
}
In the Harmony 3 configuration says the app has a maximum BSD sockets = 4, so there are memory available i guess, i tried copying and pasting the code in each app state (adding new elements), but only one socket works.
My problem comes in this part:
The second listen() returns with -1 SOCKETERROR , errno = EMFIle
`case APP_BSD_LISTEN:
{
/*LISTENING FOR CHANNEL 1*/
if (listen(berkeleyApp.bsdServerSocketCh2, MAX_CLIENT) == 0) {
SYS_CONSOLE_PRINT("Waiting for Client Connection on port: %d\r\n", SERVER_PORT_CH2);
}
/*LISTENING FOR CHANNEL 2*/
int algo = listen(berkeleyApp.bsdServerSocketCh1, MAX_CLIENT);
if ( algo == 0) {
SYS_CONSOLE_PRINT("Waiting for Client Connection on port: %d\r\n", SERVER_PORT_CH1);
}
SYS_CONSOLE_PRINT("listen channel 2: %d",algo);
berkeleyApp.state = APP_BSD_OPERATION;
}
break;`
Glad if you can help me!

How to set up a UNIX domain socket in iOS?

I am trying to set up a UNIX domain socket in iOS. According to https://iphonedevwiki.net/index.php/Unix_sockets, this is the code that I used to set up the socket on the server side:
const char *socket_path = "/var/run/myserver.socket";
// setup socket
struct sockaddr_un local;
strcpy(local.sun_path, socket_path);
unlink(local.sun_path);
local.sun_family = AF_UNIX;
int listenfd = socket(AF_UNIX, SOCK_STREAM, 0);
printf("listenfd: %d\n", listenfd);
// start the server
int r = -1;
while(r != 0) {
r = bind(listenfd, (struct sockaddr*)&local, sizeof(local));
printf("bind: %d\n", r);
usleep(200 * 1000);
}
int one = 1;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
// start listening for new connections
r = -1;
while(r != 0) {
r = listen(listenfd, 20);
printf("listen: %d\n", r);
usleep(200 * 1000);
}
// wait for new connection, and then process it
int connfd = -1;
while(true) {
if(connfd == -1) {
// wait for new connection
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
printf("new connfd: %d\n", connfd);
}
// process incoming data
char buffer[4096];
int len = recv(connfd, buffer, sizeof(buffer), 0);
if(len == 0) {
printf("connfd %d disconnected!\n", connfd);
connfd = -1;
continue;
} else {
printf("connfd %d recieved data: %s", connfd, buffer);
// send some data back (optional)
const char *response = "got it!\n";
send(connfd, response, strlen(response) + 1, 0);
}
}
However, when I run this code on my iPhone, I got this in the console:
listenfd: 3
bind: -1
bind: -1
bind: -1
bind: -1
bind: -1
...
It looks like there is a problem when we do bind() as it returns -1, I want to know what I am doing wrong in the code?
The errno is 1, which is OPERATION_NOT_PERMITTED
You are not allowed to create objects in /var/run on iOS. You need to put the socket in a directory where you are allowed to create objects, like FileManager.shared.temporaryDirectory.

How does my C application communicate with bluetoothctl?

In C language, I want to develop an application to run bluetoothctl, and then send command to it and receive the info, like we run bluetoothctl in console.
int main(void)
{
int fd, err = 0;
char* tty;
wait_pid = -1;
printf("BLEapp program start.......\r\n");
if (wait_pid == -1) {
printf("Start to run bluetoothctl......\r\n");
if ((pid = fork()) < 0) {
err = 1;
printf("Create new progress failed.\r\n");
}
else if (pid == 0) {
// Child progress, run as default when xid = 0x0 and mastAddr = 0x0
execl("/root/bluez-5.42/client/bluetoothctl", "bluetoothctl", NULL);
}
}
else {
printf("The child procress is still running.....\r\n");
err = 1;
}
//tty = ttyname(STDIN_FILENO);
//printf("stdin name is %s.\r\n", tty);
//fd = open(tty, O_WRONLY);
//if (fd < 0) {
// printf("Open stdin error..............\r\n");
//}
while (1) {
sleep(2);
fputs("devices\n", stdin);
//write(fd, "devices\n", 8);
}
return err;
}
I run bluetoothctl as child process, and want to send "devices\n" command to it, and read the listed devices. But it doesn't work.
Please help me to fix this problem.
Thanks.

Xlib Muti-thread program only works under strace

I'm writing a muti-thread program using xlib, pthread and cairo.
This program create a thread in order to draw ten points after a click event.
The problem is:
After the program drew three points, it got crashed and xlib complaint
X Error of failed request: BadRequest (invalid request code or no such operation)
Major opcode of failed request: 0 ()
Serial number of failed request: 67
Current serial number in output stream: 97
However, it can work properly when I'm using strace like "strace ./a.out".
Here's my code-clips:
void *draw_point(void *arg) { //paint random-postion point
int i = 0;
int seed;
double x ,y;
srand(seed);
cairo_set_source_rgba (cairo, 1, 0.2, 0.2, 0.6);
for(i = 0; i< 10; i++) {
x = rand() % 200;
y = rand() % 200;
if(candraw) {
cairo_arc (cairo, x, y, 10.0, 0, 2*M_PI);
cairo_fill (cairo);
}
hasdraw = true;
sleep(1);
}
return NULL;
}
bool win_main(void)
{
int clickx = 0, clicky = 0;
unsigned long valuemask;
XEvent event;
valuemask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionMask;
XSelectInput(display, win, valuemask);
pthread_t thread;
while (1) {
while (XPending(display) == 0) {
candraw = true;
if(hasdraw)
XFlush(display);
candraw = false;
}
XNextEvent(display, &event);
candraw = false;
switch (event.type) {
case MotionNotify:
//...
break;
case ButtonPress:
clickx = event.xbutton.x;
clicky = event.xbutton.y;
if(clicky < 50)
pthread_create(&thread, NULL, draw_point, NULL);
break;
case ButtonRelease:
//...
break;
default:
break;
}
}
return 0;
}
Does anyone has an idea about this weird problem?
Thanks a lot!
The problem is caused by using multi-threading with the 2 threads trying to access the display at the same.
strace will change the timing, so the threads are accessing the display at different times.
Xlib does have functions to prevent conflict. Lookup XInitThreads, which enables thread support and XLockDisplay and XUnlockDisplay, which you will need to call from each thread before and after accessing the display.

Problem with wsarecv while using with IOCP

I am new to IOCP and struggling with this for last few weeks.
I have pasted some core part of my code below related to IOCP.This may not be executed perfectly as I clipped some part to make it easy to understand.
I am struggling while receiving the data.As it comes to wsarecv in worket thread, wsarecv returns WSA_IO_PENDING error code so I call WSAGetOverlappedResult to check operation to be completed.
Twist comes here, rather it proceed and call my local function ProcessTelegramData after WSAGetOverlappedResult , same part of code(wsarecv called again) is executed again by another worker thread which try to call ProcessTelegramData and buffer value is invalid in it.
I am unable to understand
why another thread calling wsarecv again when WSAGetOverlappedResult is called and
why buffer value is getting invalidated?
unsigned LicTCPServer::WorkerThread(LPVOID lpParam)
{
//int nThreadNo = (int)lpParam;
LicTCPServer* pThis = reinterpret_cast<LicTCPServer*>(lpParam);
void *lpContext = NULL;
OVERLAPPED *pOverlapped = NULL;
CClientContext *pClientContext = NULL;
DWORD dwBytesTransfered = 0;
int nBytesRecv = 0;
int nBytesSent = 0;
DWORD dwBytes = 0, dwFlags = 0;
//Worker thread will be around to process requests, until a Shutdown event is not Signaled.
while (WAIT_OBJECT_0 != WaitForSingleObject(g_hShutdownEvent, 0))
{
BOOL bReturn = GetQueuedCompletionStatus(
g_hIOCompletionPort,
&dwBytesTransfered,
(LPDWORD)&lpContext,
&pOverlapped,
INFINITE);
if (NULL == lpContext)
{
//We are shutting down
break;
}
//Get the client context
pClientContext = (CClientContext *)lpContext;
if ((FALSE == bReturn) /*|| ((TRUE == bReturn) && (0 == dwBytesTransfered))*/)
{
//Client connection gone, remove it.
pThis->RemoveFromClientListAndFreeMemory(pClientContext);
continue;
}
WSABUF *p_wbuf = pClientContext->GetWSABUFPtr();
OVERLAPPED *p_ol = pClientContext->GetOVERLAPPEDPtr();
//printf("reached %d\n",pClientContext->GetOpCode());
printf("Get Queued received\n");
switch (pClientContext->GetOpCode())
{
case OP_READ:
{
//Once the data is successfully received, we will print it.
//pClientContext->SetOpCode(OP_WRITE);
pClientContext->ResetWSABUF();
dwFlags = 0;
//int a = recv(pClientContext->GetSocket(), p_wbuf->buf, p_wbuf->len, 0);
//Get the data.
if(WSARecv(pClientContext->GetSocket(), p_wbuf, 1, &dwBytes, &dwFlags, p_ol, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSA_IO_PENDING)
{
printf("Error occured at WSARecv()\n");
return 0;
}
}
DWORD byteTr = 0;
WSAGetOverlappedResult(pClientContext->GetSocket(),p_ol,&byteTr,TRUE,&dwFlags);
if( byteTr > 0 )
{
//doing some operatin on data received
printf("Process tele called\n");
g_pLicServFunc->ProcessTelegramData(pClientContext->GetSocket(), p_wbuf->buf, byteTr);
}
if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSARecv().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
}
break;
case OP_WRITE:
char szBuffer[MAX_BUFFER_LEN];
//Send the message back to the client.
pClientContext->SetOpCode(OP_READ);
pClientContext->SetTotalBytes(dwBytesTransfered);
pClientContext->SetSentBytes(0);
//p_wbuf->len = dwBytesTransfered;
dwFlags = 0;
DWORD temp;
//Overlapped send
printf("reached Going to send\n");
//send(pClientContext->GetSocket(), p_wbuf->buf,p_wbuf->len, 0);
nBytesSent = WSASend(pClientContext->GetSocket(), p_wbuf, 1,
&temp, dwFlags, p_ol, NULL);
if ((SOCKET_ERROR == nBytesSent) && (WSA_IO_PENDING != WSAGetLastError()))
{
//WriteToConsole("\nThread %d: Error occurred while executing WSASend().", nThreadNo);
//Let's not work with this client
//TBC
//RemoveFromClientListAndFreeMemory(pClientContext);
}
break;
default:
printf("reached to default\n");
//We should never be reaching here, under normal circumstances.
break;
} // switch
} // while
return 0;
}
I had a similar issue with WSARecv where it always queued to the io completion queue, even if it succeeded immediately. I had to ignore a return value indicating success and instead handle the queued result that I got from GetQueuedCompletionStatus.

Resources