Thread overview | |||||||||
---|---|---|---|---|---|---|---|---|---|
|
August 20, 2014 User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
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(); } --------------------------------------------------------------------------------- |
August 20, 2014 Re: User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
Posted in reply to blake kim | 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.
|
August 20, 2014 Re: User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | 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:
>> 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.
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.
|
August 20, 2014 Re: User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
Posted in reply to blake kim | 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: >> 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. > > 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. 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; } |
August 20, 2014 Re: User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
Posted in reply to blake kim Attachments: | 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. |
August 20, 2014 Re: User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
Posted in reply to blake kim | "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. |
August 21, 2014 Re: User data of epoll event is reported abnormally by epoll_wait. | ||||
---|---|---|---|---|
| ||||
Posted in reply to blake kim | 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!
|
Copyright © 1999-2021 by the D Language Foundation