Windows: Redirect stdout/stderr to NUL instead of temp files. Avoids unnecessary creation of temp files

This commit is contained in:
Kovid Goyal 2014-11-13 10:56:53 +05:30
parent a7899be02d
commit d0a44763f8
3 changed files with 15 additions and 41 deletions

View File

@ -7,26 +7,15 @@
#ifdef GUI_APP #ifdef GUI_APP
int WINAPI int WINAPI
wWinMain(HINSTANCE Inst, HINSTANCE PrevInst, wWinMain(HINSTANCE Inst, HINSTANCE PrevInst, wchar_t *CmdLine, int CmdShow) {
wchar_t *CmdLine, int CmdShow) {
wchar_t *stdout_redirect, *stderr_redirect, basename[50];
set_gui_app((char)1); set_gui_app((char)1);
MultiByteToWideChar(CP_UTF8, 0, BASENAME, -1, basename, 50); // Redirect stdout and stderr to NUL so that python does not fail writing to them
redirect_out_stream(stdout);
redirect_out_stream(stderr);
stdout_redirect = redirect_out_stream(basename, (char)1); execute_python_entrypoint(BASENAME, MODULE, FUNCTION);
stderr_redirect = redirect_out_stream(basename, (char)0);
execute_python_entrypoint(BASENAME, MODULE, FUNCTION,
stdout_redirect, stderr_redirect);
if (stdout != NULL) fclose(stdout);
if (stderr != NULL) fclose(stderr);
DeleteFile(stdout_redirect);
DeleteFile(stderr_redirect);
return 0; // This should really be returning the value set in the WM_QUIT message, but I cannot be bothered figuring out how to get that. return 0; // This should really be returning the value set in the WM_QUIT message, but I cannot be bothered figuring out how to get that.
} }
@ -37,7 +26,7 @@ wWinMain(HINSTANCE Inst, HINSTANCE PrevInst,
int wmain(int argc, wchar_t *argv) { int wmain(int argc, wchar_t *argv) {
int ret = 0; int ret = 0;
set_gui_app((char)0); set_gui_app((char)0);
ret = execute_python_entrypoint(BASENAME, MODULE, FUNCTION, NULL, NULL); ret = execute_python_entrypoint(BASENAME, MODULE, FUNCTION);
return ret; return ret;
} }

View File

@ -276,8 +276,7 @@ void setup_streams() {
setup_stream("stderr", "strict", CP_UTF8); setup_stream("stderr", "strict", CP_UTF8);
} }
void initialize_interpreter(wchar_t *outr, wchar_t *errr, void initialize_interpreter(const char *basename, const char *module, const char *function) {
const char *basename, const char *module, const char *function) {
DWORD sz; char *buf, *path; HMODULE dll; DWORD sz; char *buf, *path; HMODULE dll;
int *flag, i, argc; int *flag, i, argc;
wchar_t *app_dir, **wargv; wchar_t *app_dir, **wargv;
@ -353,11 +352,6 @@ void initialize_interpreter(wchar_t *outr, wchar_t *errr,
PySys_SetObject("calibre_module", PyBytes_FromString(module)); PySys_SetObject("calibre_module", PyBytes_FromString(module));
PySys_SetObject("calibre_function", PyBytes_FromString(function)); PySys_SetObject("calibre_function", PyBytes_FromString(function));
if (GUI_APP && outr && errr) {
PySys_SetObject("stdout_redirect", PyUnicode_FromWideChar(outr, wcslen(outr)));
PySys_SetObject("stderr_redirect", PyUnicode_FromWideChar(errr, wcslen(outr)));
}
wargv = CommandLineToArgvW(GetCommandLineW(), &argc); wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
if (wargv == NULL) ExitProcess(show_last_error(L"Failed to get command line")); if (wargv == NULL) ExitProcess(show_last_error(L"Failed to get command line"));
argv = PyList_New(argc); argv = PyList_New(argc);
@ -450,13 +444,12 @@ int calibre_show_python_error(const wchar_t *preamble, int code) {
return _show_error(preamble, L"", code); return _show_error(preamble, L"", code);
} }
int execute_python_entrypoint(const char *basename, const char *module, const char *function, int execute_python_entrypoint(const char *basename, const char *module, const char *function) {
wchar_t *outr, wchar_t *errr) {
PyObject *site, *main, *res; PyObject *site, *main, *res;
int ret = 0; int ret = 0;
load_python_dll(); load_python_dll();
initialize_interpreter(outr, errr, basename, module, function); initialize_interpreter(basename, module, function);
site = PyImport_ImportModule("site"); site = PyImport_ImportModule("site");
@ -511,18 +504,13 @@ wchar_t* get_temp_filename(const wchar_t *prefix) {
return szTempName; return szTempName;
} }
wchar_t* redirect_out_stream(const wchar_t *prefix, char outstream) { void redirect_out_stream(FILE *stream) {
FILE *f = NULL; FILE *f = NULL;
wchar_t *temp_file; wchar_t *temp_file;
errno_t err; errno_t err;
temp_file = get_temp_filename(prefix); err = freopen_s(&f, "NUL", "wt", stream);
err = _wfreopen_s(&f, temp_file, L"a+t", (outstream) ? stdout : stderr);
if (err != 0) { if (err != 0) {
ExitProcess(show_last_error_crt(L"Failed to redirect stdout.")); ExitProcess(show_last_error_crt(L"Failed to redirect stdout/stderr to NUL. This indicates a corrupted Windows install.\r\n You should contact Microsoft for assistance and/or follow the steps described here:\r\n http://bytes.com/topic/net/answers/264804-compile-error-null-device-missing"));
} }
return temp_file;
} }

View File

@ -37,12 +37,9 @@
ExIm void set_gui_app(char yes); ExIm void set_gui_app(char yes);
ExIm char is_gui_app(); ExIm char is_gui_app();
// Redirect output streams to a temporary file // Redirect output streams to NUL
// The temporary file name is returned it should be ExIm void redirect_out_stream(FILE *stream);
// free'ed with LocalFree
// If outstream is true redirects stdout, otherwise redirects stderr
ExIm wchar_t* redirect_out_stream(const wchar_t *prefix, char outstream);
// Execute python entry point defined by: module and function // Execute python entry point defined by: module and function
ExIm int execute_python_entrypoint(const char *basename, const char *module, const char *function, wchar_t *stdout_redirect, wchar_t *stderr_redirect); ExIm int execute_python_entrypoint(const char *basename, const char *module, const char *function);