Home > front end >  How to write data into global variables from callback function?
How to write data into global variables from callback function?

Time:09-03

According to windows API docs we can use global variable to pass data from creating thread to the new thread and I am assuming the opposite is also possible

Data can also be passed from the creating thread to the new thread using global variables.

Here is a data structure and a callback function, ptr is a pointer to heap allocated memory in main

typedef struct Output
{
    char *ptr;
    DWORD len;

}Output, *POutput;

Output out; // global variable 


DWORD grab_output(LPVOID args)
{ 
    DWORD dread;
    BOOL success = FALSE;
    while (1)
    {
        success = ReadFile(g_hChildStd_OUT_Rd,out.ptr, 1024, &dread, NULL);
        if (!success || dread == 0 ) break;
        out.ptr = realloc(out.ptr, out.len 1024);
        out.len  = dread;
    }   
}


int run()
{
    BOOL res; 
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    SECURITY_ATTRIBUTES sa;
    DWORD   dwThreadIdArray[1];


    
    DWORD n_size; 
    memset(&si, 0 ,sizeof(si));
    memset(&pi, 0, sizeof(pi));
    memset(&sa, 0, sizeof(sa));
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;

    if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0)) 
        return GetLastError();
    
    if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
        return GetLastError();

    si.cb = sizeof(STARTUPINFOA);
    si.hStdError = g_hChildStd_OUT_Wr;
    si.hStdOutput = g_hChildStd_OUT_Wr; 
    si.dwFlags |= STARTF_USESTDHANDLES;

    if(!CreateProcess(NULL,
                        "C:\\Windows\\System32\\cmd.exe /c dir",
                        NULL,
                        NULL,               
                        TRUE,               
                        CREATE_NEW_CONSOLE,   
                        NULL,                
                        NULL,                                      
                        &si,                
                        &pi                 
                        ))
                        {
    }
    else
    {
        
        handle = CreateThread(0, 0, grab_output, NULL, 0, NULL);
    }
    return 0;
}


int main()
{
    out.ptr = malloc(1024);
    out.len = 0;
    run();
    printf("%s\n", out.ptr);

}

when running the code out.ptr returns garbage values

gcc example.c && ./a.exe 
└e╔┐═☺

for the sake of this question assume that I will be running a single thread at any given time

CodePudding user response:

The reason this prints garbage values is you assumed for no clear reason that the thread finishes before you accessed the global variable.

There's too many unchecked fault points. Right now, check every function that can error for an error return and produce output in that case, and also set a flag in another global variable. Really, you shouldn't have to, but better to much than not enough. Then close the process and thread handles you aren't using.

Now we should be able to discuss synchronization.

It looks like you want to grab all of the output at once. Thus WaitForSingleObject() on your own thread handle. To produce output incrementally, you need to track input highwater and output highwater and output only the characters in between with putc().

Don't forget to null-terminate your string either, or printf() won't be happy.

CodePudding user response:

You need some means to communicate between the thread and main() that the value has been updated. It is very likely that main() will execute the printf before the thread is done with ReadFile. Also you have a race condition where ReadFile might be writing to the buffer while printf is reading it.

Use a mutex, semaphore, event or similar to communcate between threads, then use WaitForSingleObject etc where appropriate. It's also not advisable to have a busy-loop inside the thread or to exit the creator thread main() while there are threads still running.

EDIT:
Note that you must also return 0 from the thread or your program will go haywire, if you somehow managed to get it compiling in the first place despite the missing return.

  • Related