digitalmars.D - User data of epoll event is reported abnormally by epoll_wait.
- blake kim (95/95) Aug 19 2014 I am a newbie on D and studying interfacing to C API.
- Dominikus Dittes Scherkl (4/7) Aug 19 2014 Default alignment in D is pointersize (size_t) - so 8 on 64bit.
- blake kim (8/16) Aug 20 2014 epoll_wait is a system API on Linux.
- blake kim (17/34) Aug 20 2014 I found the solution.
- ketmar via Digitalmars-d (3/3) Aug 20 2014 On Wed, 20 Aug 2014 10:01:05 +0000
- Etienne (3/8) Aug 21 2014 Wow, that fixes my issue! I couldn't use more than 1 event in my array
- Daniel Murphy (4/7) Aug 20 2014 With default alignment, the D layout must match the C layout. I've fun ...
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(); } ---------------------------------------------------------------------------------
Aug 19 2014
On Wednesday, 20 August 2014 at 06:11:42 UTC, blake kim wrote: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 ?Default alignment in D is pointersize (size_t) - so 8 on 64bit. But most C compilers default to 4 regardless of pointersize. I think this is more a bug in C than in D.
Aug 19 2014
On Wednesday, 20 August 2014 at 06:17:43 UTC, Dominikus Dittes Scherkl wrote:On Wednesday, 20 August 2014 at 06:11:42 UTC, blake kim wrote:epoll_wait is a system API on Linux. So, I can't agree that it is a bug of C in alignment. C uses 4 byte alignment, then, I think, it is sensible that D should follow that. Actually, In core.sys.linux.epoll.d, struct epoll_event doesn't assign a specific align so that the problem is caused.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 ?Default alignment in D is pointersize (size_t) - so 8 on 64bit. But most C compilers default to 4 regardless of pointersize. I think this is more a bug in C than in D.
Aug 20 2014
On Wednesday, 20 August 2014 at 07:02:52 UTC, blake kim wrote:On Wednesday, 20 August 2014 at 06:17:43 UTC, Dominikus Dittes Scherkl wrote:I found the solution. This is a obvious bug of core.sys.linux.epoll.d. The default alignment of all of both C and D is 8 on 64bit OS. But epoll_event is packed as follows.(/usr/include/x86_64-linux-gnu/sys/epoll.h) struct epoll_event { uint32_t events; /* Epoll events */ epoll_data_t data; /* User data variable */ } __attribute__ ((__packed__)); Therefore, epoll_event should be declared in D as follows. extern(C) align(1) struct epoll_event { align(1): uint events; epoll_data_t data; }On Wednesday, 20 August 2014 at 06:11:42 UTC, blake kim wrote:epoll_wait is a system API on Linux. So, I can't agree that it is a bug of C in alignment. C uses 4 byte alignment, then, I think, it is sensible that D should follow that. Actually, In core.sys.linux.epoll.d, struct epoll_event doesn't assign a specific align so that the problem is caused.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 ?Default alignment in D is pointersize (size_t) - so 8 on 64bit. But most C compilers default to 4 regardless of pointersize. I think this is more a bug in C than in D.
Aug 20 2014
On Wed, 20 Aug 2014 10:01:05 +0000 blake kim via Digitalmars-d <digitalmars-d puremagic.com> wrote: fill bugreport, please. and submit PR if you can.
Aug 20 2014
On 2014-08-20 6:01 AM, blake kim wrote:extern(C) align(1) struct epoll_event { align(1): uint events; epoll_data_t data; }Wow, that fixes my issue! I couldn't use more than 1 event in my array because of misalignment, thanks!
Aug 21 2014
"blake kim" wrote in message news:slmejjrekoahgbmtitpo forum.dlang.org...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)With default alignment, the D layout must match the C layout. I've fun a fuzz-tester on this on linux64, so you can be reasonable confident DMD will behave correctly for structs containing basic types.
Aug 20 2014