diff --git a/generator/kmod_test.go b/generator/kmod_test.go index 830a06e0..c356b2e1 100644 --- a/generator/kmod_test.go +++ b/generator/kmod_test.go @@ -20,6 +20,8 @@ import ( func TestModuleNames(t *testing.T) { t.Parallel() + increaseOpenFileLimit() + ver, err := readKernelVersion() require.NoError(t, err) diff --git a/generator/main.go b/generator/main.go index aa74ea95..9f392e1b 100644 --- a/generator/main.go +++ b/generator/main.go @@ -65,6 +65,8 @@ func runGenerator() error { defer pprof.StopCPUProfile() } + increaseOpenFileLimit() + conf, err := readGeneratorConfig(*configFile) if err != nil { return err diff --git a/generator/util.go b/generator/util.go index 27debfc0..e0614483 100644 --- a/generator/util.go +++ b/generator/util.go @@ -1,6 +1,10 @@ package main -import "regexp" +import ( + "regexp" + + "golang.org/x/sys/unix" +) // parseProperties parses input in form of "PROP1=VAL1\nPROP2=VAL2\n..." into a map func parseProperties(data string) map[string]string { @@ -13,3 +17,35 @@ func parseProperties(data string) map[string]string { return result } + +// Opening a lot of module files in parallel requires high limit of open file descriptors +func increaseOpenFileLimit() { + limit := unix.Rlimit{ + Cur: unix.RLIM_INFINITY, + Max: unix.RLIM_INFINITY, + } + + // first try to set the process limit to infinity + if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &limit); err == nil { + // it worked! + return + } + + // if the current process unprivileged then the only thing we can do is to set soft limit to max limit value + + if err := unix.Getrlimit(unix.RLIMIT_NOFILE, &limit); err != nil { + warning("unable to get open file limit: %v", err) + return + } + + if limit.Cur >= limit.Max { + return // nothing to increase + } + + debug("increasing open file limit %d->%d", limit.Cur, limit.Max) + limit.Cur = limit.Max + + if err := unix.Setrlimit(unix.RLIMIT_NOFILE, &limit); err != nil { + warning("unable to increase rlimit: %v", err) + } +}