Eric Pouech pouech-eric@wanadoo.fr writes:
Ferenc Wagner a écrit :
Hacking away on winetest I encountered the following problem: under Windows and Wine (running cross compiled binaries) it's possible to redirect the stdout of a child process with CreateProcess using STARTF_USESTDHANDLES. However, if I CreateProcess an .exe.so from the WineLib version, the redirection is ignored. The create_process function in process.c acts on this option in both cases, but I didn't investigate further. Does anybody have an idea why this happens?
which winelib pgm did you used ?
winetest. Apply the enclosed patch to get the version I have.
did you check that the program was actually using the inherited handles (thru the standard headers) and wasn't opening itself the handles ?
Sorry, I don't understand this. What headers do you mean?
(btw kernel/tests/process.c just implemnents what you describe (on a winelib app - the test app itself) and works just fine here, the inherited handle being a pipe)
Then I may be misusing the pipe api. I would be grateful if you had a look at the patched program and point out my mistakes. Meanwhile I check out the process test program.
(The Makefile.in patch is simply for faster compilation. Half of the rest has already been submitted but not committed.)
Feri.
Index: Makefile.in =================================================================== RCS file: /home/wine/wine/programs/winetest/Makefile.in,v retrieving revision 1.24 diff -u -r1.24 Makefile.in --- Makefile.in 24 Mar 2004 23:40:06 -0000 1.24 +++ Makefile.in 25 Mar 2004 16:48:20 -0000 @@ -20,22 +20,22 @@
TESTS = \ advapi32 \ - comctl32 \ - gdi32 \ - kernel32 \ - msvcrt \ - netapi32 \ - ntdll \ - oleaut32 \ - rpcrt4 \ - shell32 \ - shlwapi \ - urlmon \ - user32 \ - wininet \ - winmm \ - winspool.drv \ - ws2_32 + comctl32 +# gdi32 \ +# kernel32 \ +# msvcrt \ +# netapi32 \ +# ntdll \ +# oleaut32 \ +# rpcrt4 \ +# shell32 \ +# shlwapi \ +# urlmon \ +# user32 \ +# wininet \ +# winmm \ +# winspool.drv \ +# ws2_32
@MAKE_PROG_RULES@
Index: main.c =================================================================== RCS file: /home/wine/wine/programs/winetest/main.c,v retrieving revision 1.8 diff -u -r1.8 main.c --- main.c 24 Mar 2004 23:40:06 -0000 1.8 +++ main.c 25 Mar 2004 16:48:20 -0000 @@ -56,7 +56,7 @@ };
static struct wine_test *wine_tests; -static struct rev_info *rev_infos; +static struct rev_info *rev_infos = NULL;
static const char *wineloader;
@@ -226,44 +226,68 @@ test->exename); }
+HANDLE +my_popen (char *cmd) +{ + HANDLE pipeRead, pipeWrite; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + + sa.nLength = sizeof sa; + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = TRUE; + if (!CreatePipe (&pipeRead, &pipeWrite, &sa, 0)) + report (R_FATAL, "Can't create pipe: %d", GetLastError ()); + + GetStartupInfo (&si); + si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + si.hStdOutput = pipeWrite; + if (!CreateProcess (NULL, cmd, NULL, NULL, TRUE, 0, + NULL, NULL, &si, &pi)) + report (R_FATAL, "Can't execute '%s': %d", cmd, GetLastError ()); + CloseHandle (pi.hThread); + CloseHandle (pi.hProcess); + CloseHandle (pipeWrite); + return pipeRead; +} + void get_subtests (const char *tempdir, struct wine_test *test, int id) { - char *subname; - FILE *subfile; - size_t subsize, bytes_read, total; - char *buffer, *index; + size_t total; + char buffer[8192], *index; const char header[] = "Valid test names:", seps[] = " \r\n"; - int oldstdout; - const char *argv[] = {"wine", NULL, NULL}; int allocated;
- subname = tempnam (0, "sub"); - if (!subname) report (R_FATAL, "Can't name subtests file."); - oldstdout = dup (1); - if (-1 == oldstdout) report (R_FATAL, "Can't preserve stdout."); - subfile = fopen (subname, "w+b"); - if (!subfile) report (R_FATAL, "Can't open subtests file."); - if (-1 == dup2 (fileno (subfile), 1)) - report (R_FATAL, "Can't redirect output to subtests."); - fclose (subfile); + HANDLE pipe; + DWORD bytes_read; + + test->subtest_count = 0;
extract_test (test, tempdir, id); - argv[1] = test->exename; - if (test->is_elf) - spawnvp (_P_WAIT, wineloader, argv); - else - spawnvp (_P_WAIT, test->exename, argv+1); - subsize = lseek (1, 0, SEEK_CUR); - buffer = xmalloc (subsize+1); + pipe = my_popen (test->exename);
- lseek (1, 0, SEEK_SET); total = 0; - while ((bytes_read = read (1, buffer + total, subsize - total)) - && (signed)bytes_read != -1) - total += bytes_read; - if (bytes_read) - report (R_FATAL, "Can't get subtests of %s", test->name); + while (ReadFile (pipe, buffer+total, sizeof buffer-1-total, + &bytes_read, NULL)) { + if (bytes_read == 0) { /* FIXME for Wine */ + SetLastError (ERROR_BROKEN_PIPE); + break; + } + total += bytes_read; + if (total >= sizeof buffer-1) { + report (R_ERROR, "Subtest list of %s is bigger than %d bytes", + test->name, sizeof buffer); + return; + } + } + if (GetLastError () != ERROR_BROKEN_PIPE) + report (R_FATAL, "Can't get subtests of %s: %d", + test->name, GetLastError ()); + CloseHandle (pipe); + buffer[total] = 0; index = strstr (buffer, header); if (!index) @@ -273,7 +297,6 @@
allocated = 10; test->subtests = xmalloc (allocated * sizeof(char*)); - test->subtest_count = 0; index = strtok (index, seps); while (index) { if (test->subtest_count == allocated) { @@ -287,13 +310,7 @@ test->subtests = xrealloc (test->subtests, test->subtest_count * sizeof(char*)); free (buffer); - close (1); - if (-1 == dup2 (oldstdout, 1)) - report (R_FATAL, "Can't recover old stdout."); - close (oldstdout); - if (remove (subname)) - report (R_FATAL, "Can't remove subtests file."); - free (subname); + }
/* Return number of failures, -1 if couldn't spawn process. */ @@ -335,8 +352,6 @@ SetErrorMode (SEM_FAILCRITICALERRORS);
if (!(wineloader = getenv("WINELOADER"))) wineloader = "wine"; - if (setvbuf (stdout, NULL, _IONBF, 0)) - report (R_FATAL, "Can't unbuffer output.");
tempdir = tempnam (0, "wct"); if (!tempdir) Index: util.c =================================================================== RCS file: /home/wine/wine/programs/winetest/util.c,v retrieving revision 1.4 diff -u -r1.4 util.c --- util.c 19 Mar 2004 19:15:23 -0000 1.4 +++ util.c 25 Mar 2004 16:48:20 -0000 @@ -19,6 +19,7 @@ * */ #include <windows.h> +#include <unistd.h> #include <errno.h>
#include "winetest.h" @@ -39,26 +40,14 @@ return p; }
-void xprintf (const char *fmt, ...) -{ - va_list ap; - - va_start (ap, fmt); - if (vprintf (fmt, ap) < 0) - report (R_FATAL, "Can't write logs: %d", errno); - va_end (ap); -} - -char *vstrmake (size_t *lenp, va_list ap) +char *vstrfmtmake (size_t *lenp, const char *fmt, va_list ap) { - char *fmt; size_t size = 1000; char *p, *q; int n;
p = malloc (size); if (!p) return NULL; - fmt = va_arg (ap, char*); while (1) { n = vsnprintf (p, size, fmt, ap); if (n < 0) size *= 2; /* Windows */ @@ -75,6 +64,14 @@ return p; }
+char *vstrmake (size_t *lenp, va_list ap) +{ + const char *fmt; + + fmt = va_arg (ap, const char*); + return vstrfmtmake (lenp, fmt, ap); +} + char *strmake (size_t *lenp, ...) { va_list ap; @@ -85,6 +82,26 @@ if (!p) report (R_FATAL, "Out of memory."); va_end (ap); return p; +} + +void xprintf (const char *fmt, ...) +{ + va_list ap; + size_t size; + ssize_t written; + char *buffer, *head; + + va_start (ap, fmt); + buffer = vstrfmtmake (&size, fmt, ap); + head = buffer; + va_end (ap); + while ((written = write (1, head, size)) < size) { + if (written == -1) + report (R_FATAL, "Can't write logs: %d", errno); + head += written; + size -= written; + } + free (buffer); }
char *