@@ -87,6 +87,21 @@ unsafe fn termination_handler() {
87
87
//
88
88
// on windows, a non-reentrant static mutex is used, so it is
89
89
// 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.
90
105
remote:: CONTAINER = None ;
91
106
92
107
// EOWNERDEAD, seems to be the same on linux, macos, and bash on windows.
0 commit comments