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();
}
---------------------------------------------------------------------------------

Reply via email to