User data of epoll event is reported abnormally by epoll_wait.
blake kim via Digitalmars-d
digitalmars-d at puremagic.com
Tue Aug 19 23:11:41 PDT 2014
I am a newbie on D and studying interfacing to C API.
I found abnormal work of epoll_wait.
I stored an arbitrary 64bit number to u64 of epoll_event and
registered the event with valid fd using epoll_ctl.
When the fd is activated on EPOLLIN, I found u64 value is not
normal.
epoll has lost the high 4 bytes and just report low 4 bytes.
For example,
import core.sys.linux.epoll;
...
epoll_event event;
event.events = EPOLLIN;
event.u64 = 0x1122334455667788;
epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &event);
...
int nfd = epoll_wait(...,&epollevent,...)
...
assert(epollevent.u64==0x1122334455667788); // ==> u64 value is
55667788
In my investigation, this problem appears by memory align
mismatch.
In C, sizeof(epoll_event) is 12 but D tells this is
16.(epoll_event.sizeof)
I wonder why there is this difference between C and D in default
align.
I got the normal result by modifying epoll_event as follows
manually.
struct epoll_event {
align(4):
uint events;
epoll_data_t data;
}
But I don't think this is right. Many C APIs need structure as
argument and adjusting align each structure doesn't make sense.
Is this problem a Bug of D ?
I tested this problem on ubuntu 64bit and full example source as
follows.
-----------------------------------------------------------------------
import std.stdio;
import core.sys.linux.epoll;
import core.sys.posix.unistd;
import std.conv;
import core.thread;
enum {
EFD_SEMAPHORE = octal!1,
EFD_CLOEXEC = octal!2000000,
EFD_NONBLOCK = octal!4000
}
extern(C) int eventfd(uint initval, int flags);
void testepoll() {
class MyThr: Thread {
int msgfd;
this() {
super(&thread_proc);
}
void thread_proc() {
int efd = epoll_create(10);
int fd = eventfd(0, EFD_NONBLOCK);
msgfd =fd;
epoll_event event;
event.events = EPOLLIN;
event.data.u64 = 0x1122334455667788;
epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event);
ulong val=1;
core.sys.posix.unistd.write(msgfd, &val, 8);
int nfd;
epoll_event pollevent;
for(;;) {
nfd = epoll_wait(efd, &pollevent, 1, -1);
if(nfd>0) {
ulong d = pollevent.data.u64;
writefln("user, %0x", d); // -> print out is 55667788, high
4 bytes(0x11223344) is lost !!!
break;
}
}
}
}
auto thr = new MyThr();
thr.start();
thr.join();
}
void main() {
testepoll();
}
---------------------------------------------------------------------------------
More information about the Digitalmars-d
mailing list