Skip to content

Is eventfd not well supported by golang? #25220

Closed
@LiangShang

Description

@LiangShang

Please answer these questions before submitting your issue. Thanks!

What version of Go are you using (go version)?

go version go1.9.5 linux/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/data3/devops/go"
GORACE=""
GOROOT="/usr/lib/golang"
GOTOOLDIR="/usr/lib/golang/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build193326714=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"

What did you do?

If possible, provide a recipe for reproducing the error.
A complete runnable program is good.
A link on play.golang.org is best.

The background is that I am writing C code to create an eventfd and fork another process, which is wrotten in Go to write on that fd.

The main logic of C code,AKA eventfd_epoll_server.c, is as follows:

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>             /* Definition of uint64_t */

#include <errno.h>
#include <sys/epoll.h>


#define handle_error(msg) \
   do { perror(msg); exit(EXIT_FAILURE); } while (0)

int _epollfd, _eventfd;

int init()
{
    _epollfd = epoll_create1(0);
    if (_epollfd == -1) handle_error("epollfd");
    _eventfd = eventfd(0, EFD_NONBLOCK);
    if (_eventfd == -1) handle_error("eventfd");
    printf("_eventfd is %d\n", _eventfd);
    struct epoll_event evnt = {0};
    evnt.data.fd = _eventfd;
    evnt.events = EPOLLIN | EPOLLET;
    if (epoll_ctl(_epollfd, EPOLL_CTL_ADD, _eventfd, &evnt) == -1)
        abort();
}

void run_server()
{
    static const int EVENTS = 20;
    struct epoll_event evnts[EVENTS];
    while (1) {
        int count = epoll_wait(_epollfd, evnts, EVENTS, -1);
        printf("epoll_wait returns %d count\n", count);
        if (count == -1)
        {
            if (errno != EINTR)
            {
                perror("epoll_wait");
                return ;
            }
        }

        int i;
        for (i = 0; i < count; ++i)
        {
            struct epoll_event *e = evnts + i;
            if (e->data.fd == _eventfd)
            {
                eventfd_t val;
                eventfd_read(_eventfd, &val);
                printf("DING: %lld\n", (long long)val);
                return ;
            }
        }
    }
}


int main(int argc, char *argv[])
{
   init();

   int ret = fork();
   if(ret == 0)
   {
       printf("child process writes to fd %d\n", _eventfd);
       char str[2];
       sprintf(str, "%d", _eventfd);
       execl("./eventfd_client", "./eventfd_client", str, (char*) NULL);

   }
   else
   {
       run_server();
   }
}

And the Golang code, AKA eventfd_client.go, is as follows:

package main

import (
	"os"
	"strconv"
	"fmt"
	"syscall"
)

func main(){
	fmt.Println(os.Args)
	fdStr := os.Args[1]
	fd, err := strconv.Atoi(fdStr)
	if err != nil {
		panic(err)
	}
	p := []byte("")
	syscall.Write(fd, p)
	if err != nil {
		panic(err)
	}
}

Then I go build eventfd_client.go and gcc gcc eventfd_epoll_server.c -std=c99 -o eventfd_epoll_server, followed by ./eventfd_epoll_server and it says

_eventfd is 4
child process writes to fd 4
[./eventfd_client 4]
panic: invalid argument

I have found from website and was told this error is caused by "receiver is nil". But I do not know why.

Further more, I use cgo and it is fixed, with the new eventfd_client.go file as follows.

package main

import (
	"os"
	"strconv"
	"fmt"
	// #include <sys/eventfd.h>
	"C"
)

func main(){
	fmt.Println(os.Args)
	fdStr := os.Args[1]
	fd, err := strconv.Atoi(fdStr)
	if err != nil {
		panic(err)
	}
	C.eventfd_write(C.int(fd), 1)
	if err != nil {
		panic(err)
	}
}

What did you expect to see?

_eventfd is 4
child process writes to fd 4
[./eventfd_client 4]
epoll_wait returns 1 count
DING: 1

What did you see instead?

As mentioned above, an error is returned by syscall.Write(fd, p).

Conclusion

So I am not sure whether it is because eventfd is not well supported by golang so far.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions