- ThreadPool::destroy used to iterate _threads directly while another
thread could be adjusting the same vector. Snapshot the vector
under the mutex and iterate the local copy for pthread_cancel /
pthread_join.
- ObjPool::construct now returns NULL when the pooled allocator
returns NULL instead of invoking placement-new on a null
pointer. In destroy, compute to_node(obj) before running the
destructor - the destructor may scrub bytes the to_node helper
reads.
- In the async/sync workers in fuse_loop, msgbuf_alloc can return
NULL under memory pressure. Fail the worker cleanly with a
diagnostic rather than dereferencing. Also introduce a small
_nproc() helper that treats hardware_concurrency()==0 as 1, so
the downstream min/max arithmetic doesn't produce a zero thread
count.
The low-level init/destroy callbacks were passed a userdata pointer
that mergerfs never consumed - the caller threaded it through
fuse_lowlevel_new only to hand it back unchanged. Remove the
parameter from the ops struct, from fuse_lowlevel_new(_common),
and from the internal fuse_ll struct; update fuse_lib_init and
fuse_lib_destroy accordingly.
Also drop fuse_reply_ioctl_iov: no caller in-tree invokes it and
the public API is defined by this vendored libfuse fork.