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

alberts opened this issue Mar 16, 2013 · 3 comments


Copy link

@alberts alberts commented Mar 16, 2013

What steps will reproduce the problem?

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?


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
    /home/alberts/bork.go:153 +0x34

goroutine 2 [syscall]:

goroutine 7 [chan send]:
    /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)?


Which operating system are you using?


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


Please provide any additional information below.

revision 631535312f2b works

revision f9c03cd9bd84 introduced the bug


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

This comment has been minimized.

Copy link

@dvyukov dvyukov commented Mar 16, 2013

Comment 1:

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)); = EPOLLIN|EPOLLOUT|EPOLLET;
        CHECK(epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &ev));
        CHECK(fd1 = dup(fds[0]));
#ifndef FIX
        CHECK(fd2 = dup(fd1));
        CHECK(epoll_ctl(epfd, EPOLL_CTL_ADD, fd2, &ev));
        CHECK(epoll_ctl(epfd, EPOLL_CTL_ADD, fd1, &ev));
        return 0;
And if you compile it with -DFIX, then it does not.
It seems the be a serious misdesign of epoll API:
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.


This comment has been minimized.

Copy link

@dvyukov dvyukov commented Mar 16, 2013

Comment 2:


This comment has been minimized.

Copy link

@dvyukov dvyukov 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.
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.