QueueUserAPC access violation on x86

1

I'm trying to use QueueUserAPC to run some function asyncronously on a specific thread. My code is working ok when compiled for x64, but when I compile and run for x86, I get an access violation.

At the end of my post is a minimal, complete example that shows what I am trying to do (cleanup of thread and events omitted for brevity).

On my machine, when I compile and run for "x64", I get the expected output:

waiting...

async function!

waiting...

async function!

waiting...

ConsoleApplication3.exe (process 17100) exited with code 0.

When I compile and run for "x86", I get:

waiting...

async function!

And then the access violation, here:

if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)

Exception thrown at 0x776227FB (ntdll.dll) in ConsoleApplication3.exe: 0xC0000005: Access violation reading location 0x36623194.

What am I doing wrong?

Full example:

#include "pch.h"
#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>

DWORD ThreadFunction(LPVOID param)
{
    while (true)
    {
        printf("waiting...\n");

        if (WaitForSingleObjectEx(param, INFINITE, TRUE) == WAIT_OBJECT_0)
            break;
    }

    ExitThread(0);
    return 0;
}

void AsyncFunction(UINT_PTR param)
{
    printf("async function!\n");
}

int main()
{
    HANDLE hThread, hStopEvent;
    DWORD threadID;

    hStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) ThreadFunction, hStopEvent, 0, &threadID);

    Sleep(1000);

    QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);

    Sleep(1000);

    QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);

    Sleep(1000);

    SetEvent(hStopEvent);

    WaitForSingleObject(hThread, INFINITE);
}
multithreading
winapi
access-violation
asked on Stack Overflow Mar 21, 2019 by TheNextman

1 Answer

2

There are two mistakes with my AsyncFunction definition:

1 - The parameter type should be ULONG_PTR, not UINT_PTR. This was actually a copy-paste error from my real implementation

2 - Missing calling convention from the function

void AsyncFunction(UINT_PTR param) should be void CALLBACK AsyncFunction(ULONG_PTR param)

And then there is no need for the cast to PAPCFUNC here:

QueueUserAPC((PAPCFUNC) AsyncFunction, hThread, NULL);

answered on Stack Overflow Mar 21, 2019 by TheNextman

User contributions licensed under CC BY-SA 3.0