Skip to content

Commit

Permalink
Python launcher: don’t assume that argv[0] is the program name.
Browse files Browse the repository at this point in the history
This should fix #14343.

PiperOrigin-RevId: 419401678
  • Loading branch information
Googler authored and copybara-github committed Jan 3, 2022
1 parent 2d93032 commit 732e9ef
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 9 deletions.
27 changes: 27 additions & 0 deletions src/test/py/bazel/launcher_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,33 @@ def testPyBinaryArgumentPassing(self):

self._buildAndCheckArgumentPassing('foo', 'bin')

def testPyBinaryLauncherWithDifferentArgv0(self):
"""Test for https://github.com/bazelbuild/bazel/issues/14343."""
self.CreateWorkspaceWithDefaultRepos('WORKSPACE')
self.ScratchFile('foo/BUILD', [
'py_binary(',
' name = "bin",',
' srcs = ["bin.py"],',
')',
])
self.ScratchFile('foo/bin.py', ['print("Hello world")'])

exit_code, stdout, stderr = self.RunBazel(['info', 'bazel-bin'])
self.AssertExitCode(exit_code, 0, stderr)
bazel_bin = stdout[0]

# Verify that the build of our py_binary succeeds.
exit_code, _, stderr = self.RunBazel(['build', '//foo:bin'])
self.AssertExitCode(exit_code, 0, stderr)

# Try to run the built py_binary.
binary_suffix = '.exe' if self.IsWindows() else ''
foo_bin = os.path.join(bazel_bin, 'foo', 'bin%s' % binary_suffix)
args = [r'C:\Invalid.exe' if self.IsWindows() else '/invalid']
exit_code, stdout, stderr = self.RunProgram(args, executable=foo_bin)
self.AssertExitCode(exit_code, 0, stderr)
self.assertEqual(stdout[0], 'Hello world')

def testWindowsJavaExeLauncher(self):
# Skip this test on non-Windows platforms
if not self.IsWindows():
Expand Down
6 changes: 5 additions & 1 deletion src/test/py/bazel/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ def RunProgram(self,
env_add=None,
shell=False,
cwd=None,
allow_failure=True):
allow_failure=True,
executable=None):
"""Runs a program (args[0]), waits for it to exit.
Args:
Expand All @@ -464,13 +465,16 @@ def RunProgram(self,
cwd: string; the current working dirctory, will be self._test_cwd if not
specified.
allow_failure: bool; if false, the function checks the return code is 0
executable: string or None; executable program to run; use args[0]
if None
Returns:
(int, [string], [string]) tuple: exit code, stdout lines, stderr lines
"""
with tempfile.TemporaryFile(dir=self._test_cwd) as stdout:
with tempfile.TemporaryFile(dir=self._test_cwd) as stderr:
proc = subprocess.Popen(
args,
executable=executable,
stdout=stdout,
stderr=stderr,
cwd=(str(cwd) if cwd else self._test_cwd),
Expand Down
39 changes: 34 additions & 5 deletions src/tools/launcher/launcher_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef STRICT
#define STRICT
#endif

#ifndef NOMINMAX
#define NOMINMAX
#endif

#ifndef UNICODE
#define UNICODE
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>

#include <memory>
#include <string>

#include "src/tools/launcher/bash_launcher.h"
#include "src/tools/launcher/java_launcher.h"
Expand All @@ -33,11 +52,21 @@ using bazel::launcher::die;
using std::make_unique;
using std::unique_ptr;

static std::wstring GetExecutableFileName() {
// https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation
constexpr std::wstring::size_type maximum_file_name_length = 0x8000;
std::wstring buffer(maximum_file_name_length, L'\0');
DWORD length = GetModuleFileNameW(nullptr, &buffer.front(), buffer.size());
if (length == 0 || length >= buffer.size()) {
die(L"Failed to obtain executable filename");
}
return buffer.substr(0, length);
}

int wmain(int argc, wchar_t* argv[]) {
const std::wstring executable_file = GetExecutableFileName();
LaunchDataParser::LaunchInfo launch_info;

if (!LaunchDataParser::GetLaunchInfo(GetBinaryPathWithExtension(argv[0]),
&launch_info)) {
if (!LaunchDataParser::GetLaunchInfo(executable_file, &launch_info)) {
die(L"Failed to parse launch info.");
}

Expand All @@ -49,8 +78,8 @@ int wmain(int argc, wchar_t* argv[]) {
unique_ptr<BinaryLauncherBase> binary_launcher;

if (result->second == L"Python") {
binary_launcher =
make_unique<PythonBinaryLauncher>(launch_info, argc, argv);
binary_launcher = make_unique<PythonBinaryLauncher>(
launch_info, executable_file, argc, argv);
} else if (result->second == L"Bash") {
binary_launcher = make_unique<BashBinaryLauncher>(launch_info, argc, argv);
} else if (result->second == L"Java") {
Expand Down
2 changes: 1 addition & 1 deletion src/tools/launcher/python_launcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ ExitCode PythonBinaryLauncher::Launch() {
// In case the given binary path is a shortened Windows 8dot3 path, we need to
// convert it back to its long path form before using it to find the python
// file.
wstring full_binary_path = GetWindowsLongPath(args[0]);
wstring full_binary_path = GetWindowsLongPath(executable_file_);
if (use_zip_file == L"1") {
python_file = GetBinaryPathWithoutExtension(full_binary_path) + L".zip";
} else {
Expand Down
11 changes: 9 additions & 2 deletions src/tools/launcher/python_launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
#ifndef BAZEL_SRC_TOOLS_LAUNCHER_PYTHON_LAUNCHER_H_
#define BAZEL_SRC_TOOLS_LAUNCHER_PYTHON_LAUNCHER_H_

#include <string>
#include <utility>

#include "src/tools/launcher/launcher.h"

namespace bazel {
Expand All @@ -23,10 +26,14 @@ namespace launcher {
class PythonBinaryLauncher : public BinaryLauncherBase {
public:
PythonBinaryLauncher(const LaunchDataParser::LaunchInfo& launch_info,
int argc, wchar_t* argv[])
: BinaryLauncherBase(launch_info, argc, argv) {}
std::wstring executable_file, int argc, wchar_t* argv[])
: BinaryLauncherBase(launch_info, argc, argv),
executable_file_(std::move(executable_file)) {}
~PythonBinaryLauncher() override = default;
ExitCode Launch() override;

private:
std::wstring executable_file_;
};

} // namespace launcher
Expand Down

0 comments on commit 732e9ef

Please sign in to comment.