diff --git a/checkin_notes b/checkin_notes index b846a027e6..3c80e161a2 100644 --- a/checkin_notes +++ b/checkin_notes @@ -223,3 +223,12 @@ David 24 Nov 2006 wrapper/ job.xml +David 25 Nov 2006 + - wrapper: redirection of stdin/stdout wasn't + working correctly on Windows. + Need to open files with CreateFile(). + + win_build/ + samples.sln + wrapper/ + wrapper.C diff --git a/win_build/samples.sln b/win_build/samples.sln index d5c54610f3..6449a57c4f 100644 --- a/win_build/samples.sln +++ b/win_build/samples.sln @@ -69,12 +69,15 @@ Global {F243B93C-73CB-44E7-9BDC-847BB95A27CA}.Debug|Win32.ActiveCfg = Debug|Win32 {F243B93C-73CB-44E7-9BDC-847BB95A27CA}.Debug|Win32.Build.0 = Debug|Win32 {F243B93C-73CB-44E7-9BDC-847BB95A27CA}.Release|Win32.ActiveCfg = Release|Win32 + {F243B93C-73CB-44E7-9BDC-847BB95A27CA}.Release|Win32.Build.0 = Release|Win32 {A9647CEA-644D-4C0A-8733-D916CD344859}.Debug|Win32.ActiveCfg = Debug|Win32 {A9647CEA-644D-4C0A-8733-D916CD344859}.Debug|Win32.Build.0 = Debug|Win32 {A9647CEA-644D-4C0A-8733-D916CD344859}.Release|Win32.ActiveCfg = Release|Win32 + {A9647CEA-644D-4C0A-8733-D916CD344859}.Release|Win32.Build.0 = Release|Win32 {F1BE6109-586D-448E-8C5B-D5C2CB874EA2}.Debug|Win32.ActiveCfg = Debug|Win32 {F1BE6109-586D-448E-8C5B-D5C2CB874EA2}.Debug|Win32.Build.0 = Debug|Win32 {F1BE6109-586D-448E-8C5B-D5C2CB874EA2}.Release|Win32.ActiveCfg = Release|Win32 + {F1BE6109-586D-448E-8C5B-D5C2CB874EA2}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/wrapper/wrapper.C b/wrapper/wrapper.C index 772085678c..6d170afdbb 100644 --- a/wrapper/wrapper.C +++ b/wrapper/wrapper.C @@ -129,6 +129,49 @@ int parse_job_file() { return ERR_XML_PARSE; } +#ifdef _WIN32 +// CreateProcess() takes HANDLEs for the stdin/stdout. +// We need to use CreateFile() to get them. Ugh. +// +HANDLE win_fopen(const char* path, const char* mode) { + SECURITY_ATTRIBUTES sa; + memset(&sa, 0, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + + if (!strcmp(mode, "r")) { + return CreateFile( + path, + GENERIC_READ, + FILE_SHARE_READ, + &sa, + OPEN_EXISTING, + 0, 0 + ); + } else if (!strcmp(mode, "w")) { + return CreateFile( + path, + GENERIC_WRITE, + FILE_SHARE_WRITE, + &sa, + OPEN_ALWAYS, + 0, 0 + ); + } else if (!strcmp(mode, "a")) { + return CreateFile( + path, + GENERIC_WRITE, + FILE_SHARE_WRITE, + &sa, + OPEN_ALWAYS, + 0, 0 + ); + } else { + return 0; + } +} +#endif + // the "state file" might tell us which app we're in the middle of, // what the starting CPU time is, etc. // @@ -136,24 +179,11 @@ void parse_state_file() { } int TASK::run() { - FILE* stdout_file; - FILE* stdin_file; - string app_path; + string app_path, stdout_path, stdin_path; boinc_resolve_filename_s(application.c_str(), app_path); - // open stdout, stdin if file names are given - // NOTE: if the application is restartable, the following - // should use "a" instead of "w". - // - if (stdout_filename != "") { - stdout_file = freopen(stdout_filename.c_str(), "w", stdout); - if (!stdout_file) return ERR_FOPEN; - } - if (stdin_filename != "") { - stdin_file = freopen(stdin_filename.c_str(), "r", stdin); - if (!stdin_file) return ERR_FOPEN; - } + #ifdef _WIN32 PROCESS_INFORMATION process_info; STARTUPINFO startup_info; @@ -166,9 +196,15 @@ int TASK::run() { // pass std handles to app // startup_info.dwFlags = STARTF_USESTDHANDLES; - startup_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - startup_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); - startup_info.hStdError = GetStdHandle(STD_ERROR_HANDLE); + if (stdout_filename != "") { + boinc_resolve_filename_s(stdout_filename.c_str(), stdout_path); + startup_info.hStdOutput = win_fopen(stdout_path.c_str(), "w"); + } + if (stdin_filename != "") { + boinc_resolve_filename_s(stdin_filename.c_str(), stdin_path); + startup_info.hStdInput = win_fopen(stdin_path.c_str(), "r"); + } + startup_info.hStdError = win_fopen(STDERR_FILE, "a"); if (!CreateProcess( app_path.c_str(), @@ -191,13 +227,31 @@ int TASK::run() { char progname[256], buf[256]; char* argv[256]; char arglist[4000]; + FILE* stdout_file; + FILE* stdin_file; pid = fork(); if (pid == -1) { boinc_finish(ERR_FORK); } if (pid == 0) { - // construct argv + // we're in the child process here + // + // open stdout, stdin if file names are given + // NOTE: if the application is restartable, + // we should deal with atomicity somehow + // + if (stdout_filename != "") { + boinc_resolve_filename_s(stdout_filename.c_str(), stdout_path); + stdout_file = freopen(stdout_path.c_str(), "w", stdout); + if (!stdout_file) return ERR_FOPEN; + } + if (stdin_filename != "") { + boinc_resolve_filename_s(stdin_filename.c_str(), stdin_path); + stdin_file = freopen(stdin_path.c_str(), "r", stdin); + if (!stdin_file) return ERR_FOPEN; + } + // construct argv // strcpy(buf, app_path.c_str()); argv[0] = buf;