c++ - Cannot read from pipe in separate thread from suspended process -


i trying create process createprocess in suspended state , read it's stdout. base took msdn code. after creating process i'm going set job restrictions(not implemented yet) on process , i'm starting reading in separate thread stdout pipe. before thread initiated resume suspended process. in result i'm getting nothing readfile call, stops , waits data arrive when process finished. here code

#include <windows.h> #include <tchar.h> #include <stdio.h> #include <strsafe.h> #define bufsize 4096 handle g_hchildstd_in_rd = null; handle g_hchildstd_in_wr = null; handle g_hchildstd_out_rd = null; handle g_hchildstd_out_rddup = null; handle g_hchildstd_out_wr = null; handle g_hsavedstd_out_wr = null; handle g_hinputfile = null; dword winapi createchildprocess(lpvoid param); void writetopipe(void); dword winapi readfrompipe(lpvoid param); void errorexit(ptstr); process_information piprocinfo; int _tmain(int argc, tchar *argv[]) { security_attributes saattr; printf("\n->start of parent execution.\n"); // set binherithandle flag pipe handles inherited. saattr.nlength = sizeof(security_attributes); saattr.binherithandle = true; saattr.lpsecuritydescriptor = null; // create pipe child process's stdout. if ( ! createpipe(&g_hchildstd_out_rd, &g_hchildstd_out_wr, &saattr, 0) ) errorexit(text("stdoutrd createpipe")); // ensure read handle pipe stdout not inherited. if ( ! sethandleinformation(g_hchildstd_out_rd, handle_flag_inherit, 0) ) errorexit(text("stdout sethandleinformation")); // create pipe child process's stdin. if (! createpipe(&g_hchildstd_in_rd, &g_hchildstd_in_wr, &saattr, 0)) errorexit(text("stdin createpipe")); // ensure write handle pipe stdin not inherited. if ( ! sethandleinformation(g_hchildstd_in_wr, handle_flag_inherit, 0) ) errorexit(text("stdin sethandleinformation")); startupinfo sistartinfo; zeromemory( &sistartinfo, sizeof(startupinfo) ); sistartinfo.cb = sizeof(startupinfo); sistartinfo.hstderror = g_hchildstd_out_wr; sistartinfo.hstdoutput = g_hchildstd_out_wr; sistartinfo.hstdinput = g_hchildstd_in_rd; sistartinfo.dwflags |= startf_usestdhandles; //createthread(&saattr,0, createchildprocess, &sistartinfo, 0, null); createchildprocess(&sistartinfo); resumethread(piprocinfo.hthread); printf( "\n->contents of child process stdout:\n\n", argv[1]); //readfrompipe(null); handle thread = createthread(&saattr,0, readfrompipe, &sistartinfo, 0, null); waitforsingleobject(thread, infinite); printf("\n->end of parent execution.\n"); // remaining open handles cleaned when process terminates. // avoid resource leaks in larger application, close handles explicitly. return 0; } dword winapi createchildprocess(lpvoid param) // create child process uses created pipes stdin , stdout. { tchar szcmdline[]=text("c:\\gnuwin32\\bin\\ls.exe"); startupinfo *sistartinfo = (startupinfo*)param; bool bsuccess = false; // set members of process_information structure. zeromemory( &piprocinfo, sizeof(process_information) ); // set members of startupinfo structure. // structure specifies stdin , stdout handles redirection. // create child process. bsuccess = createprocess(null, szcmdline, // command line null, // process security attributes null, // primary thread security attributes true, // handles inherited create_suspended | create_separate_wow_vdm | create_no_window, // creation flags null, // use parent's environment null, // use parent's current directory sistartinfo, // startupinfo pointer &piprocinfo); // receives process_information //if resumethread here - works // if error occurs, exit application. if ( ! bsuccess ) errorexit(text("createprocess")); else { // close handles child process , primary thread. // applications might keep these handles monitor status // of child process, example. closehandle(piprocinfo.hprocess); closehandle(piprocinfo.hthread); } return 0; } void writetopipe(void) // read file , write contents pipe child's stdin. // stop when there no more data. { dword dwread, dwwritten; char chbuf[bufsize]; bool bsuccess = false; (;;) { bsuccess = readfile(g_hinputfile, chbuf, bufsize, &dwread, null); if ( ! bsuccess || dwread == 0 ) break; bsuccess = writefile(g_hchildstd_in_wr, chbuf, dwread, &dwwritten, null); if ( ! bsuccess ) break; } // close pipe handle child process stops reading. if ( ! closehandle(g_hchildstd_in_wr) ) errorexit(text("stdinwr closehandle")); } dword winapi readfrompipe(lpvoid param) // read output child process's pipe stdout // , write parent process's pipe stdout. // stop when there no more data. { dword dwread, dwwritten; char chbuf[bufsize]; bool bsuccess = false; handle hparentstdout = getstdhandle(std_output_handle); (;;) { bsuccess = readfile( g_hchildstd_out_rd, chbuf, bufsize, &dwread, null); if( ! bsuccess || dwread == 0 ) break; bsuccess = writefile(hparentstdout, chbuf, dwread, &dwwritten, null); if (! bsuccess ) break; } return 0; } void errorexit(ptstr lpszfunction) // format readable error message, display message box, // , exit application. { lpvoid lpmsgbuf; lpvoid lpdisplaybuf; dword dw = getlasterror(); formatmessage( format_message_allocate_buffer | format_message_from_system | format_message_ignore_inserts, null, dw, makelangid(lang_neutral, sublang_default), (lptstr) &lpmsgbuf, 0, null ); lpdisplaybuf = (lpvoid)localalloc(lmem_zeroinit, (lstrlen((lpctstr)lpmsgbuf)+lstrlen((lpctstr)lpszfunction)+40)*sizeof(tchar)); stringcchprintf((lptstr)lpdisplaybuf, localsize(lpdisplaybuf) / sizeof(tchar), text("%s failed error %d: %s"), lpszfunction, dw, lpmsgbuf); messagebox(null, (lpctstr)lpdisplaybuf, text("error"), mb_ok); localfree(lpmsgbuf); localfree(lpdisplaybuf); exitprocess(1); } 

and if call resumethread(piprocinfo.hthread); after createprocess function - works well. need keep creation in separate function anyway , call resumethread few functions after. so, make program suspended process's output in separate thread.

always check return values.

you're trying call resumethread on handle that's been closed. if had checked return value, you'd have noticed function wasn't succeeding, have told problem was.

remove closehandle(piprocinfo.hthread) createchildprocess , call resumethread work.

you should closing g_hchildstd_out_wr , g_hchildstd_in_rd after creating child process, can tell when child process exits.


Comments

Popular posts from this blog

javascript - backbone.js Collection.add() doesn't `construct` (`initialize`) an object -

c++ - Accessing inactive union member and undefined behavior? -

php - Get uncommon values from two or more arrays -