Skip to content

Commit 682e665

Browse files
authored
server: explicitly set exec path when create new instance (#17669)
* Revert "rm unused fn" This reverts commit f2dbe9c. * server: explicitly set exec path when create new instance * put back TODO * only call get_server_exec_path() once * add fallback logic
1 parent 4574f29 commit 682e665

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

tools/server/server-models.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,55 @@
2424
#include <unistd.h>
2525
#endif
2626

27+
#if defined(__APPLE__) && defined(__MACH__)
28+
// macOS: use _NSGetExecutablePath to get the executable path
29+
#include <mach-o/dyld.h>
30+
#include <limits.h>
31+
#endif
32+
2733
#define CMD_EXIT "exit"
2834

35+
static std::filesystem::path get_server_exec_path() {
36+
#if defined(_WIN32)
37+
wchar_t buf[32768] = { 0 }; // Large buffer to handle long paths
38+
DWORD len = GetModuleFileNameW(nullptr, buf, _countof(buf));
39+
if (len == 0 || len >= _countof(buf)) {
40+
throw std::runtime_error("GetModuleFileNameW failed or path too long");
41+
}
42+
return std::filesystem::path(buf);
43+
#elif defined(__APPLE__) && defined(__MACH__)
44+
char small_path[PATH_MAX];
45+
uint32_t size = sizeof(small_path);
46+
47+
if (_NSGetExecutablePath(small_path, &size) == 0) {
48+
// resolve any symlinks to get absolute path
49+
try {
50+
return std::filesystem::canonical(std::filesystem::path(small_path));
51+
} catch (...) {
52+
return std::filesystem::path(small_path);
53+
}
54+
} else {
55+
// buffer was too small, allocate required size and call again
56+
std::vector<char> buf(size);
57+
if (_NSGetExecutablePath(buf.data(), &size) == 0) {
58+
try {
59+
return std::filesystem::canonical(std::filesystem::path(buf.data()));
60+
} catch (...) {
61+
return std::filesystem::path(buf.data());
62+
}
63+
}
64+
throw std::runtime_error("_NSGetExecutablePath failed after buffer resize");
65+
}
66+
#else
67+
char path[FILENAME_MAX];
68+
ssize_t count = readlink("/proc/self/exe", path, FILENAME_MAX);
69+
if (count <= 0) {
70+
throw std::runtime_error("failed to resolve /proc/self/exe");
71+
}
72+
return std::filesystem::path(std::string(path, count));
73+
#endif
74+
}
75+
2976
struct local_model {
3077
std::string name;
3178
std::string path;
@@ -99,6 +146,14 @@ server_models::server_models(
99146
for (char ** env = envp; *env != nullptr; env++) {
100147
base_env.push_back(std::string(*env));
101148
}
149+
GGML_ASSERT(!base_args.empty());
150+
// set binary path
151+
try {
152+
base_args[0] = get_server_exec_path().string();
153+
} catch (const std::exception & e) {
154+
LOG_WRN("failed to get server executable path: %s\n", e.what());
155+
LOG_WRN("using original argv[0] as fallback: %s\n", base_args[0].c_str());
156+
}
102157
// TODO: allow refreshing cached model list
103158
// add cached models
104159
auto cached_models = common_list_cached_models();

0 commit comments

Comments
 (0)