Commit b2003abb authored by Wez Furlong's avatar Wez Furlong Committed by Facebook GitHub Bot

fb_py_win_main.c: fix File Not Found errors on windows

Summary:
This commit resolves an issue with our zipapp executables
on Windows that meant that the only reliable way to start them was
to use the fully path to the executable.

The root cause is that the __wargv array is produced by parsing the
process command line into an array, and if you ran `watchman-wait -h`
__wargv[0] would have `watchman-wait` rather than the fully qualified
path to the executable that the zipapp plumbing requires.

The fix is to ask the system for the fully qualified path and ensure that
that gets set as both argv[0] AND argv[1].

Reviewed By: xavierd

Differential Revision: D21190350

fbshipit-source-id: eeb95084592d30a028a93b2b03877f8cc6c72729
parent fca12003
...@@ -19,9 +19,49 @@ int wmain() { ...@@ -19,9 +19,49 @@ int wmain() {
fprintf(stderr, "error: failed to allocate argument vector\n"); fprintf(stderr, "error: failed to allocate argument vector\n");
return 1; return 1;
} }
pyargv[0] = __wargv[0];
for (int n = 0; n < __argc; ++n) { /* Py_Main wants the wide character version of the argv so we pull those
* values from the global __wargv array that has been prepared by MSVCRT.
*
* In order for the zipapp to run we need to insert an extra argument in
* the front of the argument vector that points to ourselves.
*
* An additional complication is that, depending on who prepared the argument
* string used to start our process, the computed __wargv[0] can be a simple
* shell word like `watchman-wait` which is normally resolved together with
* the PATH by the shell.
* That unresolved path isn't sufficient to start the zipapp on windows;
* we need the fully qualified path.
*
* Given:
* __wargv == {"watchman-wait", "-h"}
*
* we want to pass the following to Py_Main:
*
* {
* "z:\build\watchman\python\watchman-wait.exe",
* "z:\build\watchman\python\watchman-wait.exe",
* "-h"
* }
*/
#define PATH_SIZE 1024
wchar_t full_path_to_argv0[PATH_SIZE];
DWORD len = GetModuleFileNameW(NULL, full_path_to_argv0, PATH_SIZE);
if (len == 0 ||
len == PATH_SIZE && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
fprintf(
stderr,
"error: %d while retrieving full path to this executable\n",
GetLastError());
return 1;
}
for (int n = 1; n < __argc; ++n) {
pyargv[n + 1] = __wargv[n]; pyargv[n + 1] = __wargv[n];
} }
pyargv[0] = full_path_to_argv0;
pyargv[1] = full_path_to_argv0;
return Py_Main(__argc + 1, pyargv); return Py_Main(__argc + 1, pyargv);
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment