Skip to content

Commit

Permalink
Use close_range() to close large numbers of files when available.
Browse files Browse the repository at this point in the history
close_range() is a newish, Linux and FreeBSD system call to close a
large range of file descriptors as is commonly done by the child
process after a fork.  Linux now supports extremely large limits and
the traditional, brute force way of closing file descriptors can incur
a several minute delay in those situations.  This change checks for
and uses close_range() when it is available.
  • Loading branch information
gigem committed Jun 30, 2024
1 parent 1df29c9 commit 8dbc67e
Show file tree
Hide file tree
Showing 5 changed files with 31 additions and 0 deletions.
12 changes: 12 additions & 0 deletions mythtv/configure
Original file line number Diff line number Diff line change
Expand Up @@ -1934,6 +1934,7 @@ MYTHTV_HAVE_LIST='
libudev
stdint_h
sync_file_range
close_range
sys_endian_h
'

Expand Down Expand Up @@ -5644,6 +5645,17 @@ int main(int argc, char **argv){
}
EOF

# test for close_range (linux system call since 5.9 and also FreeBSD)
check_ld "cc" <<EOF && enable close_range
#define _GNU_SOURCE
#include <unistd.h>
int main(int argc, char **argv){
close_range(0,0,0);
return 0;
}
EOF

# test for sizeof(int)
for sizeof in 1 2 4 8 16; do
check_cc <<EOF && _sizeof_int=$sizeof && break
Expand Down
4 changes: 4 additions & 0 deletions mythtv/libs/libmythbase/mythsystemunix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1110,8 +1110,12 @@ void MythSystemLegacyUnix::Fork(std::chrono::seconds timeout)
}

/* Close all open file descriptors except stdin/stdout/stderr */
#if HAVE_CLOSE_RANGE
close_range(3, sysconf(_SC_OPEN_MAX) - 1, 0);
#else
for( int fd = sysconf(_SC_OPEN_MAX) - 1; fd > 2; fd-- )
close(fd);
#endif

/* set directory */
if( directory && chdir(directory) < 0 )
Expand Down
5 changes: 5 additions & 0 deletions mythtv/libs/libmythtv/recorders/ExternalStreamHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <QFile>

// MythTV headers
#include "config.h"
#include "libmythbase/exitcodes.h"

#include "ExternalChannel.h"
Expand Down Expand Up @@ -401,8 +402,12 @@ void ExternIO::Fork(void)
}

/* Close all open file descriptors except stdin/stdout/stderr */
#if HAVE_CLOSE_RANGE
close_range(3, sysconf(_SC_OPEN_MAX) - 1, 0);
#else
for (int i = sysconf(_SC_OPEN_MAX) - 1; i > 2; --i)
close(i);
#endif

/* Set the process group id to be the same as the pid of this
* child process. This ensures that any subprocesses launched by this
Expand Down
6 changes: 6 additions & 0 deletions mythtv/programs/mythbackend/mythbackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include <QProcessEnvironment>
#endif

#include <unistd.h>

// MythTV
#include "libmythbase/cleanupguard.h"
#include "libmythbase/compat.h"
Expand Down Expand Up @@ -86,8 +88,12 @@ int main(int argc, char **argv)
}

#ifndef _WIN32
#if HAVE_CLOSE_RANGE
close_range(UNUSED_FILENO, sysconf(_SC_OPEN_MAX) - 1, 0);
#else
for (long i = UNUSED_FILENO; i < sysconf(_SC_OPEN_MAX) - 1; ++i)
close(i);
#endif
QCoreApplication a(argc, argv);
#else
// MINGW application needs a window to receive messages
Expand Down
4 changes: 4 additions & 0 deletions mythtv/programs/mythpreviewgen/mythpreviewgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,12 @@ int main(int argc, char **argv)
}

#ifndef _WIN32
#if HAVE_CLOSE_RANGE
close_range(UNUSED_FILENO, sysconf(_SC_OPEN_MAX) - 1, 0);
#else
for (long i = UNUSED_FILENO; i < sysconf(_SC_OPEN_MAX) - 1; ++i)
close(i);
#endif
QCoreApplication a(argc, argv);
#else
// MINGW application needs a window to receive messages
Expand Down

0 comments on commit 8dbc67e

Please sign in to comment.