Description
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.