Count open file descriptors from within a go program

5,637 views
Skip to first unread message

Donovan Hide

unread,
Dec 31, 2012, 8:10:56 AM12/31/12
to golang-nuts
Hi,

I'm playing around with websockets and am frequently hitting the maximum file descriptor limit. I can see in the source for syscall that EMFILE is regarded as a temporary error:


Which makes for some slightly interesting debugging when no FD's are being freed :-) I can check what the limits are from within go using something like:

var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
log.Fatal("Getrlimit:" + err.Error())
}
log.Printf("%v file descriptors out of a maximum of %v available\n", limit.Cur, limit.Max)

My question: is there a way to access the actual open file descriptors count from within a Go program using a syscall?

Cheers,
Donovan.

bryanturley

unread,
Dec 31, 2012, 11:35:50 AM12/31/12
to golan...@googlegroups.com
If you are in linux you can check /proc/<PID>/fd/ not sure how complete that info is though.

Ian Ragsdale

unread,
Jun 12, 2013, 4:00:31 PM6/12/13
to golan...@googlegroups.com, bryan...@gmail.com
Hmm, is there really no way to do this in a cross-platform way? I'd like to figure out that I'm near the open file limit, so I can stop accepting more work, and I'd rather do that before I hit the file limit & start generating errors. I suppose I could read the proc filesystem, but that doesn't work on my dev machine (a mac).

- Ian

minux

unread,
Jun 12, 2013, 4:19:13 PM6/12/13
to Ian Ragsdale, golan...@googlegroups.com, bryan...@gmail.com
On Thu, Jun 13, 2013 at 4:00 AM, Ian Ragsdale <ian.ra...@gmail.com> wrote:
Hmm, is there really no way to do this in a cross-platform way? I'd like to figure out that I'm near the open file limit, so I can stop accepting more work, and I'd rather do that before I hit the file limit & start generating errors. I suppose I could read the proc filesystem, but that doesn't work on my dev machine (a mac).
shell out to lsof(1) and grep the result?

Ian Ragsdale

unread,
Jun 12, 2013, 4:37:21 PM6/12/13
to minux, golan...@googlegroups.com, bryan...@gmail.com
Hah, that just occurred to me about 10 minutes ago. :) It's better than nothing, I just find it kind of weird that this seems to be nearly impossible from Go, although I guess that's because there's really no good way to do it from C either. It looks like you can play some tricks with poll() to figure out which handles are open, but it's ugly too.

For future reference for anyone else trying to figure this out, here's my basic solution:

func countOpenFiles() int {
out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("lsof -p %v", os.Getpid())).Output()
if err != nil {
log.Fatal(err)
}
lines := strings.Split(string(out), "\n")
return len(lines) - 1
}

Seems to work out of the box on recent versions of Mac OS and Ubuntu, I'm guessing most unix-like boxes should probably work.

- Ian

minux

unread,
Jun 12, 2013, 4:43:35 PM6/12/13
to Ian Ragsdale, golan...@googlegroups.com, bryan...@gmail.com
On Thu, Jun 13, 2013 at 4:37 AM, Ian Ragsdale <ian.ra...@gmail.com> wrote:
Hah, that just occurred to me about 10 minutes ago. :) It's better than nothing, I just find it kind of weird that this seems to be nearly impossible from Go, although I guess that's because there's really no good way to do it from C either. It looks like you can play some tricks with poll() to figure out which handles are open, but it's ugly too.
yeah, there are plenty of syscall that could be (ab)used to determine whether a given
fd is open or not, but it will be too ugly a hack. 

For future reference for anyone else trying to figure this out, here's my basic solution:

func countOpenFiles() int {
out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("lsof -p %v", os.Getpid())).Output()
if err != nil {
log.Fatal(err)
}
lines := strings.Split(string(out), "\n")
return len(lines) - 1
you can just bytes.Count(out, []byte("\n")) here
}

Alexey Verkhovsky

unread,
Aug 25, 2015, 3:44:01 PM8/25/15
to golang-nuts
lsof -p performs a linear scan of ALL open file descriptors on a server, therefore takes too long (and abuses CPU) on a really busy web server.

Tristan Colgate

unread,
Aug 25, 2015, 4:32:24 PM8/25/15
to Alexey Verkhovsky, golang-nuts

If you're on Linux, and aren't too fussed about portability, you could read /proc/self,fd ?


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages