-
Notifications
You must be signed in to change notification settings - Fork 82
Description
As far as I'm aware, yagna is a multi-threaded application; please correct me if I'm wrong.
There are multiple locations where pre_exec closures use the system allocator:
golem_cli/src/command/yagna.rs:383,utils/process/src/lib.rs:{58,78},test-utils/test-framework/src/yagna.rs:102invokestd::io::Error::other, which allocates (see Document Error::{new,other} as to be avoided in pre_exec rust-lang/rust#148971). This is why I originally stumbled upon this problem, but that's not the only issue.exe-unit/tokio-process-ns/src/pre_exec.rsallocates many times, both directly via calls toformat!, and indirectly by invoking operations on paths, which require allocation to append NUL bytes.
Allocating in pre_exec is bad in multi-threaded programs. If forking happens while the allocator lock is held by another thread, deadlocks can occur, since there's no one left in the new process to unlock the mutex. I do not believe this is UB, and modern libc offer protections against this issue, but this isn't POSIX-compliant and should preferably be avoided.
A valid fix would be to use impl From<nix::Error> for std::io::Error. This also ensures the correct error code is forwarded to the parent process, instead of the default -EINVAL. I do not understand why this wasn't done in some places, and .map_err(Into::into) was used in others, since ? already performs From-conversion, but I'm not familiar with your codebase, so maybe there's a reason for that.
I could not quickly discern whether exe-unit/tokio-process-ns/src/pre_exec.rs is invoked from multi-threaded contexts. Since it's called for tokio::process::Command in exe-unit/tokio-process-ns/src/lib.rs:35, I would assume that's the case, but I'm not sure. If that's the case, the code should either be rearchitectured to allocate outside of pre_exec, or invoke non-allocating APIs from libc and avoid format!.