
























Yes, libraries in the POSIX world have some extra limitations due to global state (e.g., in the most general case, cannot use signals unless explicitly documented). But I don't think spawning child processes is such a limitation. As long as some library does clean posix_spawn, it'll work fine. (Or even if it does fork+exec, then there's still a decent chance for it to work, because bugs around pthread_atfork are uncommon)
There are real complications with waiting for child completion, which can make subprocesses potentially unusable from the library context. I am not sure about an exhaustive list, but setting SIGCHLD to SIG_IGN will "eat" process termination status. Or the main process could get confused by either SIGCHLD or wait() reporting and consuming "unexpected" child completion. I might be wrong, but I don't think Linux has extensions to avoid those issues. Still, on my system, I recently started seeing those glycin-rs sub-processes for doing image decoding in a sandbox. But this is likely implemented by gtk "stack," which already wraps subprocesses' business in the glib main loop thingy, so it can handle those wait{,id,pid} issues in a centralized fashion.
So perhaps if spawning children needs to be extended on Linux, it should be around consuming child terminations, not spawning.
Things are generally getting better with time. Way back in the day, I think around 2002 or so, it used to be the case that simply linking -lpthread without even using any threads, caused my program to run 2x slower. Because glibc's malloc didn't have per-thread caching and had to do locking around malloc/free calls. And trivial locks were much more expensive back then. Effects like that were one of the reasons why gperftools had weak symbol dependency on pthread functions (we need at least pthread_key_create for per-thread caches cleanup). If pthread is linked in, we use it for correctness, otherwise we are not the reason libpthread needed to be loaded.
Since then, pthread has been completely integrated into libc.so, and the "penalty" of using threads is nearly gone. So, I think, it is more or less accepted for libraries to spawn threads at will. Or use, e.g., OpenMP, which uses threads under the hood. I am aware of one potential exception. In gcc's implementation of std::shared_ptr, there is code that checks the __libc_single_threaded flag every time the shared pointer's refcount is updated. Inlining this massive bloat everywhere. E.g.: https://godbolt.org/z/vbWKW9G4d. There might be some single-threaded programs where non-atomic refcounting is important for performance, so then simply having a library that had some thread(s) spawned under the hood will slow those down.
But IMHO, threading is common enough that it is more or less settled that threads are usable in libraries. And with time, we'll get more and more POSIX "stuff" usable from libraries, I think.
Having "meta" platforms like Go or JDK is another way to make everything work nicely in practice. In some way, wine implementing Win32 stuff is such a "meta" platform too, but Win32 is _full_ legacy and broken crap.
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。