#1004988 libbsd0: closefrom() should be async-signal-safe

Package:
libbsd0
Source:
libbsd
Description:
utility functions from BSD systems - shared library
Submitter:
Jakub Wilk
Date:
2024-10-03 02:39:01 UTC
Severity:
normal
#1004988#3
Date:
2022-02-04 22:11:29 UTC
From:
To:
closefrom() is documented to be async-signal-safe on FreeBSD:
https://www.freebsd.org/cgi/man.cgi?sigaction
I'd like it to be async-signal-safe in libbsd too.

The current implementation uses opendir()/readdir()/closedir() and
reallocarray()/close(), which are not async-signal-safe.

https://www.sourceware.org/ml/libc-alpha/2018-09/msg00270.html hints
that you can use poll() to query for open fds. That should be efficient,
portable and async-signal-safe.

#1004988#8
Date:
2024-10-03 02:25:23 UTC
From:
To:
I just saw this report, and happened to have some code to do that.  I am
attaching it for reference.  Compared to closefrom_procfs(), there would
be no efficient way to see file descriptors above the limit.  With Linux
having added close_range() a while ago, this may all be moot.

With poll(), a fall-back is needed, to deal with the "Unable to allocate
memory for kernel data structures" case, and the bizarre "The nfds value
exceeds the RLIMIT_NOFILE value".  A system call to return the next open
descriptor, equal to or greater than a specified value, would be useful;
ConnectServerInfo() can do this on QNX.

I wonder whether anything is known to depend on this async-signal-safety
or large-descriptor-handling.  Hypothetically, libbsd's non-preservation
of errno could also cause a portability problem.

(Regarding the referenced mailing list discussion, it would be better to
have multi-threaded processes never call fork(); they should have forked
while still single-threaded, creating a "fork server" to call fork() and
exec() as necessary.  Firefox does this.  It avoids problems relating to
signals, memory [over-]commitments, and the file descriptor table.)