Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions definitions/process.luau
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ function process.exit(exitcode: number): never
error("not implemented")
end

function process.execpath(): string
error("not implemented")
end

return process
17 changes: 9 additions & 8 deletions lute/cli/src/climain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "lute/time.h"
#include "lute/version.h"
#include "lute/vm.h"
#include "uv.h"

#ifdef _WIN32
#include <Windows.h>
Expand Down Expand Up @@ -293,7 +294,7 @@ static std::optional<std::string> getValidPath(std::string filePath)
return std::nullopt;
}

int handleRunCommand(int argc, char** argv, int argOffset)
int handleRunCommand(int argc, char** argv, char* argv0, int argOffset)
{
std::string filePath;
int program_argc = 0;
Expand Down Expand Up @@ -330,7 +331,7 @@ int handleRunCommand(int argc, char** argv, int argOffset)
return 1;
}

Runtime runtime;
Runtime runtime(argv0);
lua_State* L = setupCliState(runtime);

std::optional<std::string> validPath = getValidPath(filePath);
Expand Down Expand Up @@ -445,9 +446,9 @@ int handleCompileCommand(int argc, char** argv, int argOffset)
return compileScript(inputFilePath, outputFilePath, argv[0]);
}

int handleCliCommand(CliCommandResult result, int program_argc, char** program_argv)
int handleCliCommand(CliCommandResult result, int program_argc, char** program_argv, char* argv0)
{
Runtime runtime;
Runtime runtime(argv0);
lua_State* L = setupCliState(runtime);

std::string bytecode = Luau::compile(std::string(result.contents), copts());
Expand All @@ -461,7 +462,7 @@ int cliMain(int argc, char** argv)
AppendedBytecodeResult embedded = checkForAppendedBytecode(argv[0]);
if (embedded.found)
{
Runtime runtime;
Runtime runtime(argv[0]);
lua_State* GL = setupCliState(runtime);

bool success = runBytecode(runtime, embedded.BytecodeData, "=__EMBEDDED__", GL, argc, argv);
Expand All @@ -485,7 +486,7 @@ int cliMain(int argc, char** argv)

if (strcmp(command, "run") == 0)
{
return handleRunCommand(argc, argv, argOffset);
return handleRunCommand(argc, argv, argv[0], argOffset);
}
else if (strcmp(command, "check") == 0)
{
Expand All @@ -507,12 +508,12 @@ int cliMain(int argc, char** argv)
}
else if (std::optional<CliCommandResult> result = getCliCommand(command); result)
{
return handleCliCommand(*result, argc - argOffset, &argv[argOffset]);
return handleCliCommand(*result, argc - argOffset, &argv[argOffset], argv[0]);
}
else
{
// Default to 'run' command
argOffset = 1;
return handleRunCommand(argc, argv, argOffset);
return handleRunCommand(argc, argv, argv[0], argOffset);
}
}
3 changes: 3 additions & 0 deletions lute/process/include/lute/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ int cwd(lua_State* L);

int exitFunc(lua_State* L);

int execpath(lua_State* L);

static const luaL_Reg lib[] = {
{"run", run},
{"homedir", homedir},
{"cwd", cwd},
{"exit", exitFunc},
{"execpath", execpath},

{nullptr, nullptr}
};
Expand Down
6 changes: 6 additions & 0 deletions lute/process/src/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,12 @@ int cwd(lua_State* L)
return 1;
};

int execpath(lua_State* L)
{
lua_pushstring(L, getRuntime(L)->execPath.c_str());
return 1;
}

static int envIndex(lua_State* L)
{
const char* key = luaL_checkstring(L, 2);
Expand Down
4 changes: 3 additions & 1 deletion lute/runtime/include/lute/runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ using RuntimeStep = Luau::Variant<StepSuccess, StepErr, StepEmpty>;

struct Runtime
{
Runtime();
Runtime(const char* argv0 = nullptr);
~Runtime();

bool runToCompletion();
Expand Down Expand Up @@ -81,6 +81,8 @@ struct Runtime

std::vector<ThreadToContinue> runningThreads;

std::string execPath;

private:
std::mutex continuationMutex;
std::vector<std::function<void()>> continuations;
Expand Down
28 changes: 27 additions & 1 deletion lute/runtime/src/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,42 @@

#include <string>
#include <assert.h>
#include <climits> // IWYU pragma: keep

#ifdef PATH_MAX
#define LUTE_PATH_MAX PATH_MAX
#else
#define LUTE_PATH_MAX 8192
#endif

static void lua_close_checked(lua_State* L)
{
if (L)
lua_close(L);
}

Runtime::Runtime()
static std::string getExecPath(const char* argv0)
{
// FIXME: uv_exepath requires that uv_setup_args(argc, argv) was called.
// This function can allocate on some platforms. However, the state is
// persisted for the duration of the program and cleaning it up with
// uv_library_shutdown will only delete it once. This is a problem in unit
// tests that call cliMain multiple times. There, the function would leak
// memory. On the three main platforms supported by Lute however, uv doesn't
// require uv_setup_args to be called, so it's currently left out.
char buf[LUTE_PATH_MAX];
size_t len = sizeof(buf);
if (uv_exepath(buf, &len) == 0)
return {buf, len};
if (argv0)
return argv0;
return {};
}

Runtime::Runtime(const char* argv0)
: globalState(nullptr, lua_close_checked)
, dataCopy(nullptr, lua_close_checked)
, execPath(getExecPath(argv0))
{
stop.store(false);
activeTokens.store(0);
Expand Down
2 changes: 1 addition & 1 deletion lute/vm/src/spawn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ int lua_spawn(lua_State* L)
{
const char* file = luaL_checkstring(L, 1);

auto child = std::make_shared<Runtime>();
auto child = std::make_shared<Runtime>(getRuntime(L)->execPath.c_str());

setupState(
*child,
Expand Down