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
.