From 9471869710fd3451fc5dce7b9c53b95ab810b75b Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Mon, 1 Dec 2025 23:13:28 +0100 Subject: [PATCH 1/5] Revert "rm unused fn" This reverts commit f2dbe9c087ac8776cd41f747a8b0ddf448c8399a. --- tools/server/server-models.cpp | 50 +++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index 0f812ed411b..76eeefecf9c 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -3,7 +3,7 @@ #include "download.h" -#include // TODO: remove this once we use HTTP client from download.h +#include #include #include @@ -24,8 +24,55 @@ #include #endif +#if defined(__APPLE__) && defined(__MACH__) +// macOS: use _NSGetExecutablePath to get the executable path +#include +#include +#endif + #define CMD_EXIT "exit" +static std::filesystem::path get_server_exec_path() { +#if defined(_WIN32) + wchar_t buf[32768] = { 0 }; // Large buffer to handle long paths + DWORD len = GetModuleFileNameW(nullptr, buf, _countof(buf)); + if (len == 0 || len >= _countof(buf)) { + throw std::runtime_error("GetModuleFileNameW failed or path too long"); + } + return std::filesystem::path(buf); +#elif defined(__APPLE__) && defined(__MACH__) + char small_path[PATH_MAX]; + uint32_t size = sizeof(small_path); + + if (_NSGetExecutablePath(small_path, &size) == 0) { + // resolve any symlinks to get absolute path + try { + return std::filesystem::canonical(std::filesystem::path(small_path)); + } catch (...) { + return std::filesystem::path(small_path); + } + } else { + // buffer was too small, allocate required size and call again + std::vector buf(size); + if (_NSGetExecutablePath(buf.data(), &size) == 0) { + try { + return std::filesystem::canonical(std::filesystem::path(buf.data())); + } catch (...) { + return std::filesystem::path(buf.data()); + } + } + throw std::runtime_error("_NSGetExecutablePath failed after buffer resize"); + } +#else + char path[FILENAME_MAX]; + ssize_t count = readlink("/proc/self/exe", path, FILENAME_MAX); + if (count <= 0) { + throw std::runtime_error("failed to resolve /proc/self/exe"); + } + return std::filesystem::path(std::string(path, count)); +#endif +} + struct local_model { std::string name; std::string path; @@ -318,6 +365,7 @@ void server_models::load(const std::string & name, bool auto_load) { inst.subproc = std::make_shared(); { + //std::string exec_path = get_server_exec_path().string(); SRV_INF("spawning server instance with name=%s on port %d\n", inst.meta.name.c_str(), inst.meta.port); std::vector child_args; From 3c5fc3bda1fd8ba5641c061a3c389f2c85aab0e5 Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Mon, 1 Dec 2025 23:15:52 +0100 Subject: [PATCH 2/5] server: explicitly set exec path when create new instance --- tools/server/server-models.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index 76eeefecf9c..045972eccb0 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -365,7 +365,6 @@ void server_models::load(const std::string & name, bool auto_load) { inst.subproc = std::make_shared(); { - //std::string exec_path = get_server_exec_path().string(); SRV_INF("spawning server instance with name=%s on port %d\n", inst.meta.name.c_str(), inst.meta.port); std::vector child_args; @@ -383,6 +382,9 @@ void server_models::load(const std::string & name, bool auto_load) { } } + // set executable path + child_args[0] = get_server_exec_path().string(); + // set model args add_or_replace_arg(child_args, "--port", std::to_string(inst.meta.port)); add_or_replace_arg(child_args, "--alias", inst.meta.name); From bfa8bf211108c37810db476a0c6dd3d935e04b51 Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Mon, 1 Dec 2025 23:39:34 +0100 Subject: [PATCH 3/5] put back TODO --- tools/server/server-models.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index 045972eccb0..a1be8ebc87c 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -3,7 +3,7 @@ #include "download.h" -#include +#include // TODO: remove this once we use HTTP client from download.h #include #include From 895aabbdfba9a7e9f3d48165928af05f7880894a Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Mon, 1 Dec 2025 23:41:43 +0100 Subject: [PATCH 4/5] only call get_server_exec_path() once --- tools/server/server-models.cpp | 4 ++-- tools/server/server-models.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index a1be8ebc87c..0ec57cdce44 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -139,7 +139,7 @@ server_models::server_models( const common_params & params, int argc, char ** argv, - char ** envp) : base_params(params) { + char ** envp) : base_params(params), server_binary_path(get_server_exec_path().string()) { for (int i = 0; i < argc; i++) { base_args.push_back(std::string(argv[i])); } @@ -383,7 +383,7 @@ void server_models::load(const std::string & name, bool auto_load) { } // set executable path - child_args[0] = get_server_exec_path().string(); + child_args[0] = server_binary_path; // set model args add_or_replace_arg(child_args, "--port", std::to_string(inst.meta.port)); diff --git a/tools/server/server-models.h b/tools/server/server-models.h index b9bec983ef6..01ed4cc5359 100644 --- a/tools/server/server-models.h +++ b/tools/server/server-models.h @@ -84,6 +84,7 @@ struct server_models { common_params base_params; std::vector base_args; std::vector base_env; + std::string server_binary_path; void update_meta(const std::string & name, const server_model_meta & meta); From 0dbf1e73343796e549b4f44d0d2db16bfc2e05e4 Mon Sep 17 00:00:00 2001 From: Xuan Son Nguyen Date: Tue, 2 Dec 2025 10:07:35 +0100 Subject: [PATCH 5/5] add fallback logic --- tools/server/server-models.cpp | 13 +++++++++---- tools/server/server-models.h | 1 - 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tools/server/server-models.cpp b/tools/server/server-models.cpp index 0ec57cdce44..9856869e99a 100644 --- a/tools/server/server-models.cpp +++ b/tools/server/server-models.cpp @@ -139,13 +139,21 @@ server_models::server_models( const common_params & params, int argc, char ** argv, - char ** envp) : base_params(params), server_binary_path(get_server_exec_path().string()) { + char ** envp) : base_params(params) { for (int i = 0; i < argc; i++) { base_args.push_back(std::string(argv[i])); } for (char ** env = envp; *env != nullptr; env++) { base_env.push_back(std::string(*env)); } + GGML_ASSERT(!base_args.empty()); + // set binary path + try { + base_args[0] = get_server_exec_path().string(); + } catch (const std::exception & e) { + LOG_WRN("failed to get server executable path: %s\n", e.what()); + LOG_WRN("using original argv[0] as fallback: %s\n", base_args[0].c_str()); + } // TODO: allow refreshing cached model list // add cached models auto cached_models = common_list_cached_models(); @@ -382,9 +390,6 @@ void server_models::load(const std::string & name, bool auto_load) { } } - // set executable path - child_args[0] = server_binary_path; - // set model args add_or_replace_arg(child_args, "--port", std::to_string(inst.meta.port)); add_or_replace_arg(child_args, "--alias", inst.meta.name); diff --git a/tools/server/server-models.h b/tools/server/server-models.h index 01ed4cc5359..b9bec983ef6 100644 --- a/tools/server/server-models.h +++ b/tools/server/server-models.h @@ -84,7 +84,6 @@ struct server_models { common_params base_params; std::vector base_args; std::vector base_env; - std::string server_binary_path; void update_meta(const std::string & name, const server_model_meta & meta);