From adfa5c241a70f99a26b94ab693875152e91cd858 Mon Sep 17 00:00:00 2001 From: "Alexander A. Klimov" Date: Wed, 28 May 2025 15:14:21 +0200 Subject: [PATCH] ProcessSpawnImpl(): outsource array build and Convert::ToString() to child --- lib/base/process.cpp | 77 ++++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 35 deletions(-) diff --git a/lib/base/process.cpp b/lib/base/process.cpp index 965b92864..ce6ae6905 100644 --- a/lib/base/process.cpp +++ b/lib/base/process.cpp @@ -82,30 +82,6 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques Dictionary::Ptr extraEnvironment = request->Get("extraEnvironment"); bool adjustPriority = request->Get("adjustPriority"); - // build argv - auto **argv = new char *[arguments->GetLength() + 1]; - - for (unsigned int i = 0; i < arguments->GetLength(); i++) { - String arg = arguments->Get(i); - argv[i] = strdup(arg.CStr()); - } - - argv[arguments->GetLength()] = nullptr; - - std::vector> extraEnv; - - if (extraEnvironment) { - ObjectLock olock(extraEnvironment); - - extraEnv.reserve(extraEnvironment->GetLength()); - - for (const Dictionary::Pair& kv : extraEnvironment) { - extraEnv.emplace_back(kv.first, Convert::ToString(kv.second)); - } - } - - extraEnvironment.reset(); - pid_t pid = fork(); int errorCode = 0; @@ -132,6 +108,30 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques (void)close(fds[1]); (void)close(fds[2]); + std::vector args; + std::vector argv; + ObjectLock oLock (arguments); + + try { + args.reserve(arguments->GetLength()); + argv.reserve(arguments->GetLength() + 1u); + } catch (const std::exception& ex) { + fprintf(stderr, "std::vector#reserve() failed: %s\n", ex.what()); + _exit(128); + } + + for (auto& argument : arguments) { + try { + args.emplace_back(Convert::ToString(argument)); + argv.emplace_back(args.back().GetData().data()); + } catch (const std::exception& ex) { + fprintf(stderr, "Convert::ToString() failed: %s\n", ex.what()); + _exit(128); + } + } + + argv.emplace_back(nullptr); + if (unsetenv("NOTIFY_SOCKET")) { perror("unsetenv() failed"); _exit(128); @@ -142,10 +142,23 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques _exit(128); } - for (auto& kv : extraEnv) { - if (setenv(kv.first.CStr(), kv.second.CStr(), 1)) { - perror("setenv() failed"); - _exit(128); + if (extraEnvironment) { + ObjectLock oLock (extraEnvironment); + + for (auto& kv : extraEnvironment) { + String v; + + try { + v = Convert::ToString(kv.second); + } catch (const std::exception& ex) { + fprintf(stderr, "Convert::ToString() failed: %s\n", ex.what()); + _exit(128); + } + + if (setenv(kv.first.CStr(), v.CStr(), 1)) { + perror("setenv() failed"); + _exit(128); + } } } @@ -172,7 +185,7 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques sigemptyset(&mask); sigprocmask(SIG_SETMASK, &mask, nullptr); - if (execvp(argv[0], argv) < 0) { + if (execvp(argv[0], argv.data()) < 0) { char errmsg[512]; strcpy(errmsg, "execvp("); strncat(errmsg, argv[0], sizeof(errmsg) - strlen(errmsg) - 1); @@ -188,12 +201,6 @@ static Value ProcessSpawnImpl(struct msghdr *msgh, const Dictionary::Ptr& reques (void)close(fds[1]); (void)close(fds[2]); - // free arguments - for (int i = 0; argv[i]; i++) - free(argv[i]); - - delete[] argv; - Dictionary::Ptr response = new Dictionary({ { "rc", pid }, { "errno", errorCode }