Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

runtime, net: some kind of bug in linux poller leads to -EEXIST on epoll_ctl call #5061

Closed
alberts opened this issue Mar 16, 2013 · 3 comments

Comments

Projects
None yet
4 participants
@alberts
Copy link
Contributor

commented Mar 16, 2013

What steps will reproduce the problem?

http://play.golang.org/p/jqEzJKsSCD

go build bork.go

strace -f ./bork

for some weird reason the problem only shows up when you run under strace

in my bigger internal test, I saw this without stracing it

What is the expected output?

nothing

What do you see instead?

strace shows: epoll_ctl(6, EPOLL_CTL_ADD, 4, {...}) = -1 EEXIST (File exists)

panic: errno -17

goroutine 1 [running]:
main.newClientServerConn(0xc200000300, 0x0, 0x0)
    /home/alberts/bork.go:143 +0x135
main.main()
    /home/alberts/bork.go:153 +0x34

goroutine 2 [syscall]:

goroutine 7 [chan send]:
main.func·001()
    /home/alberts/bork.go:138 +0xb9
created by main.newClientServerConn
    /home/alberts/bork.go:139 +0xdb

Which compiler are you using (5g, 6g, 8g, gccgo)?

6g

Which operating system are you using?

linux

Which version are you using?  (run 'go version')

tip

Please provide any additional information below.

revision 631535312f2b works

revision f9c03cd9bd84 introduced the bug

Attachments:

  1. strace.log.fail (42829 bytes)
  2. strace.log.ok (70558 bytes)
  3. bork.go (3127 bytes)
@dvyukov

This comment has been minimized.

Copy link
Member

commented Mar 16, 2013

Comment 1:

Thanks!
The following C programs fails with the same error:
#include <sys/epoll.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#define CHECK(...) if ((__VA_ARGS__) >= 0); else \
        exit(printf("FAILED on line %d: %s\n", __LINE__, strerror(errno)))
int main() {
        int epfd, fds[2], fd1, fd2;
        struct epoll_event ev;
        CHECK(socketpair(AF_LOCAL, SOCK_STREAM, 0, fds));
        CHECK(epfd = epoll_create1(0));
        ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
        CHECK(epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &ev));
        CHECK(fd1 = dup(fds[0]));
        CHECK(close(fds[0]));
        CHECK(close(fds[1]));
#ifndef FIX
        CHECK(fd2 = dup(fd1));
        CHECK(epoll_ctl(epfd, EPOLL_CTL_ADD, fd2, &ev));
        CHECK(close(fd2));
#else
        (void)fd2;
        CHECK(epoll_ctl(epfd, EPOLL_CTL_ADD, fd1, &ev));
#endif
        CHECK(close(fd1));
        return 0;
}
And if you compile it with -DFIX, then it does not.
It seems the be a serious misdesign of epoll API:
http://lwn.net/Articles/430804/
It makes the 'automatic unregistration on close()' feature (which I was relying on)
basically useless (misbehaving in cases like this).
Fix is coming.

Labels changed: added go1.1, removed priority-triage.

Owner changed to @dvyukov.

Status changed to Started.

@dvyukov

This comment has been minimized.

Copy link
Member

commented Mar 16, 2013

Comment 2:

mailed https://golang.org/cl/7870043/
@dvyukov

This comment has been minimized.

Copy link
Member

commented Mar 21, 2013

Comment 3:

This issue was closed by revision 4484078.

Status changed to Fixed.

@alberts alberts added fixed labels Mar 21, 2013

@rsc rsc added this to the Go1.1 milestone Apr 14, 2015

@rsc rsc removed the go1.1 label Apr 14, 2015

@golang golang locked and limited conversation to collaborators Jun 24, 2016

This issue was closed.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
You can’t perform that action at this time.