From 03a8c57f6ba53d5e430bfe5a5b032b18a1093a53 Mon Sep 17 00:00:00 2001 From: "Jeff R. Allen" Date: Wed, 8 May 2019 08:46:58 +0200 Subject: [PATCH] Apply Go 1.12/Darwin file descriptor fix Also: Improve some error reporting. --- .gitignore | 32 +++---------------- go.mod | 1 + simul/platform/deterlab.go | 2 +- simul/platform/fd_darwin.go | 62 +++++++++++++++++++++++++++++++++++++ simul/platform/fd_unix.go | 2 +- simul/platform/platform.go | 4 ++- 6 files changed, 72 insertions(+), 31 deletions(-) create mode 100644 simul/platform/fd_darwin.go diff --git a/.gitignore b/.gitignore index a8549b74..1375afa2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,34 +1,10 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof -*.iml -*.cov - config/ build/ test_data/ test/ deploy/ .tags* -profile.tmp \ No newline at end of file +*~ +profile.tmp +*.cov +.DS_Store \ No newline at end of file diff --git a/go.mod b/go.mod index 2fe6b37b..069f8a47 100644 --- a/go.mod +++ b/go.mod @@ -15,6 +15,7 @@ require ( go.dedis.ch/protobuf v1.0.6 go.etcd.io/bbolt v1.3.2 golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 // indirect + golang.org/x/sys v0.0.0-20190124100055-b90733256f2e gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/satori/go.uuid.v1 v1.2.0 gopkg.in/tylerb/graceful.v1 v1.2.15 diff --git a/simul/platform/deterlab.go b/simul/platform/deterlab.go index 19abc4e6..1125f807 100644 --- a/simul/platform/deterlab.go +++ b/simul/platform/deterlab.go @@ -215,7 +215,7 @@ func (d *Deterlab) Cleanup() error { err := SSHRunStdout(d.Login, d.Host, "test -f remote/users && ( cd remote; ./users -kill )") if err != nil { - log.Lvl1("NOT-Normal error from cleanup") + log.Lvl1("NOT-Normal error from cleanup", err.Error()) sshKill <- "error" } sshKill <- "stopped" diff --git a/simul/platform/fd_darwin.go b/simul/platform/fd_darwin.go new file mode 100644 index 00000000..f7dfa5f3 --- /dev/null +++ b/simul/platform/fd_darwin.go @@ -0,0 +1,62 @@ +package platform + +import ( + "errors" + "syscall" + + "go.dedis.ch/onet/v3/log" + "golang.org/x/sys/unix" +) + +func init() { + var rLimit syscall.Rlimit + err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + log.Fatal("Error Getting Rlimit ", err) + } + + // We observed that with Go 1.11.5, we were getting + // 24576, and then with Go 1.12, we started getting "invalid argument". + // See https://github.com/golang/go/issues/30401 + + // On Darwin, the real fd max is given by sysctl. + res, err := unix.Sysctl("kern.maxfilesperproc") + if err != nil || len(res) != 3 { + // In case of error, fall back to something reasonable. + res = "10240" + } + // res is type string, but according to sysctl(3), it should be interpreted + // as an int32. It seems to be little-endian. And for some reason, there are only + // 3 bytes. + rLimit.Max = uint64(res[0]) | uint64(res[1])<<8 | uint64(res[2])<<16 + + if rLimit.Cur < rLimit.Max { + rLimit.Cur = rLimit.Max + err = syscall.Setrlimit(syscall.RLIMIT_NOFILE, &rLimit) + if err != nil { + log.Warn("Error Setting Rlimit:", err) + } + } + + err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rLimit) + log.Info("File descriptor limit is:", rLimit.Cur) +} + +// CheckOutOfFileDescriptors tries to duplicate the stdout file descriptor +// and throws an error if it cannot do it. This is a horrible hack mainly for +// MacOSX where the file descriptor limit is quite low and we need to tell +// people running simulations what they can do about it. +func CheckOutOfFileDescriptors() error { + // Check if we're out of file descriptors + newFS, err := syscall.Dup(syscall.Stdout) + if err != nil { + return errors.New(`Out of file descriptors. You might want to do something like this for Mac OSX: + sudo sysctl -w kern.maxfiles=122880 + sudo sysctl -w kern.maxfilesperproc=102400 + sudo sysctl -w kern.ipc.somaxconn=20480`) + } + if err = syscall.Close(newFS); err != nil { + return errors.New("Couldn't close new file descriptor: " + err.Error()) + } + return nil +} diff --git a/simul/platform/fd_unix.go b/simul/platform/fd_unix.go index c8f8a573..db59078c 100644 --- a/simul/platform/fd_unix.go +++ b/simul/platform/fd_unix.go @@ -1,4 +1,4 @@ -// +build !windows +// +build !windows,!darwin package platform diff --git a/simul/platform/platform.go b/simul/platform/platform.go index 2666cef3..f23b4d72 100644 --- a/simul/platform/platform.go +++ b/simul/platform/platform.go @@ -150,8 +150,10 @@ func ReadRunFile(p Platform, filename string) []*RunConfig { // Decoding of the first part of the run config file // where the config wont change for the whole set of the simulation's tests scanner := bufio.NewScanner(file) + line := 0 for scanner.Scan() { text := scanner.Text() + line++ log.Lvl3("Decoding", text) // end of the first part if text == "" { @@ -164,7 +166,7 @@ func ReadRunFile(p Platform, filename string) []*RunConfig { // checking if format is good vals := strings.Split(text, "=") if len(vals) != 2 { - log.Fatal("Simulation file:", filename, " is not properly formatted ( key = value )") + log.Fatal("Simulation file:", filename, "line", line, "is not properly formatted ( key = value )") } // fill in the general config masterConfig.Put(strings.TrimSpace(vals[0]), strings.TrimSpace(vals[1]))