@@ -87,6 +87,21 @@ unsafe fn termination_handler() {
8787 //
8888 // on windows, a non-reentrant static mutex is used, so it is
8989 // definitely not thread safe, but this should not matter.
90+ //
91+ // NOTE: there is one major function that is not async-signal safe here:
92+ // memory allocation and deallocation, which is not async-signal safe.
93+ // this should only be run once without deadlocking since any
94+ // atomics are guaranteed to be lock-free. we cannot easily avoid
95+ // allocation/deallocation, since we would need static global muts
96+ // for basically everything. `Command::arg` and `Command::new` will
97+ // internally allocate, and freeing it will deallocate any arguments
98+ // it was provided. even if we used a static global `Command`, the
99+ // `io::Result` requires a `Box` or `io::Error`, which would allocate.
100+ // the alternative would be to use `posix_spawnp` or `CreateProcess`
101+ // directly, which are async-signal safe and thread-safe, respectively,
102+ // however, we'd need to store the engine path and the argument list as
103+ // a global CString and `Vec<CString>`, respectively. this atomic guard
104+ // makes this safe regardless.
90105 remote:: CONTAINER = None ;
91106
92107 // EOWNERDEAD, seems to be the same on linux, macos, and bash on windows.
0 commit comments