davecheney / gpio

GPIO for Go
BSD 2-Clause "Simplified" License
228 stars 52 forks source link

EpollWait: Should this check for -1 and loop? #12

Closed kardianos closed 9 years ago

kardianos commented 11 years ago

I recently got the following panic: panic: EpollWait error: interrupted system call

goroutine 3 [running]: github.com/davecheney/gpio.func·001() /home/pi/code/src/github.com/davecheney/gpio/gpio_linux.go:74 +0x1d4 created by github.com/davecheney/gpio.setupEpoll /home/pi/code/src/github.com/davecheney/gpio/gpio_linux.go:87 +0x1d8

This is on a rpi. It would seem that epoll should loop here if the err is a -1. Does this sound about right? Only reason I saw this was it was in an nohup.out log, normally runs fine.

tylerstillwater commented 11 years ago

I've seen that as well. I had it happen to me when I would ctrl+c the running program. It seems the interrupt is caught by epoll as well and it returns an error.

I'm not entirely sure what the appropriate approach is here, due to the various levels of interrupts.

Is there a situation in which the program should keep running, like a HUP? Is that the -1 you are referring to? I suppose we could detect the kill level/error and continue the loop if it is warranted. It would probably be best not to panic on interrupt at all, also.

Thoughts?

bradfitz commented 10 years ago

I just had this happen as well:

panic: EpollWait error: interrupted system call

goroutine 20 [running]: runtime.panic(0xb5420, 0x1030e0e8) /usr/local/go/src/pkg/runtime/panic.c:279 +0x1a0 github.com/davecheney/gpio.func·001() /home/pi/src/github.com/davecheney/gpio/gpio_linux.go:74 +0x1ac created by github.com/davecheney/gpio.setupEpoll /home/pi/src/github.com/davecheney/gpio/gpio_linux.go:87 +0x194

goroutine 16 [select (no cases), 15 minutes]: main.main() /home/pi/pin.go:85 +0x728

goroutine 19 [finalizer wait, 15 minutes]: runtime.park(0x25270, 0x1452b0, 0x1446f1) /usr/local/go/src/pkg/runtime/proc.c:1369 +0x5c runtime.parkunlock(0x1452b0, 0x1446f1) /usr/local/go/src/pkg/runtime/proc.c:1385 +0x40 runfinq() /usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xa0 runtime.goexit() /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 21 [chan receive, 5 minutes]: main.func·002() /home/pi/pin.go:47 +0x74 created by main.main /home/pi/pin.go:73 +0x6b4

goroutine 22 [sleep]: time.Sleep(0x1dcd6500, 0x0) /usr/local/go/src/pkg/runtime/time.goc:39 +0x3c main.func·003() /home/pi/pin.go:78 +0x68 created by main.main /home/pi/pin.go:82 +0x6f0

If you're going to do your own epoll, you need to handle EINTR and friends.

tchap commented 9 years ago

Happening to me as well, on rpi... It's bit of a pain since there is no way to prevent the panic, so the interrupt kills my process instantly...

davecheney commented 9 years ago

Must be something related to the rpi kernel. I'll try to push a fix soon.

On 22 Dec 2014, at 21:10, Ondřej Kupka notifications@github.com wrote:

Happening to me as well, on rpi... It's bit of a pain since there is no way to prevent the panic, so the interrupt kills my process instantly...

— Reply to this email directly or view it on GitHub.

tchap commented 9 years ago

Also I am getting the panic only sometimes, not always.

davecheney commented 9 years ago

Epoll is not supposed to return EAGAIN, we tell the signal handler to restart that signal. It's a kernel bug, I'll try to work around it.

On 22 Dec 2014, at 22:32, Ondřej Kupka notifications@github.com wrote:

Also I am getting the panic only sometimes, not always.

— Reply to this email directly or view it on GitHub.

isaiasma commented 9 years ago

Hi,

You are right, I think EpollWait error: interrupted system call is syscall.EINTR not syscall.EAGAIN

in go source file src/syscall/zerrors_linux_arm.go (line 1397 and line 1256)

var errors = [...]string{
...
  4:   "interrupted system call",
...
// Errors
const (
...  
  EINTR           = Errno(0x4)
...

Linux kernel source:

/usr/include/asm/errno.h
#define EAGAIN          11      /* Try again */
#define EINTR            4      /* Interrupted system call */

Stackoverflow how to handle interrupted system call