diff --git a/src/edge_process.cc b/src/edge_process.cc index 7ff9c82f..a8c34623 100644 --- a/src/edge_process.cc +++ b/src/edge_process.cc @@ -491,29 +491,15 @@ std::string DetectExecPath() { if (forced_exec != nullptr && forced_exec[0] != '\0') { return forced_exec; } -#if defined(__APPLE__) - uint32_t size = 0; - _NSGetExecutablePath(nullptr, &size); - if (size > 0) { - std::vector buf(size + 1, '\0'); - if (_NSGetExecutablePath(buf.data(), &size) == 0) { - char resolved[4096] = {'\0'}; - if (realpath(buf.data(), resolved) != nullptr) { - return MaybePreferSiblingEdgeBinary(std::string(resolved)); - } - return MaybePreferSiblingEdgeBinary(std::string(buf.data())); - } + char exec_path_buf[8192]; + size_t exec_path_len = sizeof(exec_path_buf); + if (uv_exepath(exec_path_buf, &exec_path_len) == 0) { + return MaybePreferSiblingEdgeBinary(std::string(exec_path_buf, exec_path_len)); } - return "edge"; -#elif defined(__linux__) - std::vector buf(4096, '\0'); - ssize_t n = readlink("/proc/self/exe", buf.data(), buf.size() - 1); - if (n > 0) { - buf[static_cast(n)] = '\0'; - return MaybePreferSiblingEdgeBinary(std::string(buf.data())); + if (!g_edge_argv0.empty()) { + return g_edge_argv0; } - return "edge"; -#elif defined(_WIN32) +#if defined(_WIN32) return "edge.exe"; #else return "edge"; diff --git a/src/edge_spawn_sync.cc b/src/edge_spawn_sync.cc index ee78da6b..c722d35d 100644 --- a/src/edge_spawn_sync.cc +++ b/src/edge_spawn_sync.cc @@ -734,10 +734,23 @@ void PipeShutdownCallback(uv_shutdown_t* req, int status) { auto* pipe = static_cast(req->data); if (pipe == nullptr || pipe->runner == nullptr) return; pipe->shutdown_pending = false; - if (status < 0 && status != UV_ENOTCONN) { + if (status < 0 && + status != UV_ENOTCONN +#if defined(__wasi__) + // WASIX stdin uses a one-way pipe here rather than a socket-like stream. + // Closing the writer through uv_shutdown() can surface as UV_EACCES even + // after the child has already consumed stdin successfully, so treat it as + // a close/EOF condition instead of a real spawnSync failure. + && status != UV_EACCES +#endif + ) { SetPipeErrorIfUnset(pipe->runner, status); } - if (!pipe->writable) { + if (!pipe->writable +#if defined(__wasi__) + || status == UV_EACCES +#endif + ) { ClosePipeIfNeeded(pipe); } } @@ -758,6 +771,15 @@ void StartPipeShutdown(SyncPipe* pipe) { if (!pipe->writable) ClosePipeIfNeeded(pipe); return; } +#if defined(__wasi__) + if (rc == UV_EACCES) { + // See PipeShutdownCallback(): on WASIX this means the stdin writer cannot + // be shutdown like a socket stream, not that the child spawn failed. + pipe->shutdown_pending = false; + ClosePipeIfNeeded(pipe); + return; + } +#endif if (rc < 0) { pipe->shutdown_pending = false; SetPipeErrorIfUnset(pipe->runner, rc); diff --git a/wasix/setup-wasix-deps.sh b/wasix/setup-wasix-deps.sh index d03d1919..1dac9a81 100755 --- a/wasix/setup-wasix-deps.sh +++ b/wasix/setup-wasix-deps.sh @@ -36,7 +36,7 @@ clone_or_update() { mkdir -p "${DEPS_DIR}" # Keep the upstream branch name until the external repo renames it. -clone_or_update "${DEPS_DIR}/libuv-wasix" "https://github.com/wasix-org/libuv.git" "ubi" +clone_or_update "${DEPS_DIR}/libuv-wasix" "https://github.com/wasix-org/libuv.git" "fix/spawn" clone_or_update "${DEPS_DIR}/openssl-wasix" "https://github.com/wasix-org/openssl.git" "master" echo "WASIX deps are ready under ${DEPS_DIR}"