Opening and closing files is bad for performance, so now that
we accurately track the situation of hitting too many open files
we can keep the band files open, even for the non-readbuf code
path.
This unifies the logic of opening (and caching file descriptors)
between the readbuf and non-readbuf code paths.
The previous logic was flawed anyways, as reading a range could
potentially span multiple bands, but we only checked if we were
just below the max limit.
Using the process group (now that we've got one that's exclusive
to the testrunner) allows us to also clean up children that have
been detached from their original parent (and now have PID 1 as
their parent).
The process already has some existing file descriptors open, e.g. stdin,
stdout and stderr, so we can't assume we can open as many files as the
RLIMIT_NOFILE tells us.
A different approach to this is to not use a static limit of maximum
open files, but instead react to EMFILE when trying to open new files,
and then close existing files, but as a stop gap we compute a more
accurate static value for the maximum open files.
Fixes#35
Relying on the process group to figure out which processes to treat
as children and grandchildren of the test run was not correct, as
the testrunner didn't ensure it was creating a new process group.
When running inside 'make check' the process group was actually that
of make, not testrunner.sh.
Since setpgid is not universally available, we iterate the process
tree via ps, and kill the children recursively.
getgrnam is not thread-safe on Linux (but is on macOS). To ensure
we don't call it from two threads at the same time we move its use
inside a lambda that initializes a local static. This is fine, as
we don't expect the 'nogroup' gid to change.