❦ 15 mai 2016 09:19 +0200, Willy Tarreau <w...@1wt.eu> :

>> I think this is an aliasing problem. You cannot have two incompatible
>> variables pointing at the same memory spot. It seems that now
>> sockaddr_storage and sockaddr_in are not compatible anymore.
>
> Here it's not an aliasing problem in my opinion since we build with
> -fno-strict-aliasing for this reason. Also usually when gcc produces
> an unexpected behaviour we at least have a corresponding warning, here
> it simply produces bad code.

In the past, there was a warning and many projects switched to union to
solve this. At some point, the warning disappeared. I don't know if it
was a change in the glibc (for example, the use of "restrict" keyword)
or in gcc. In the bugzilla, there are many reports of this warning
feature not being effective because it's too hard to get it right.

I suppose that some new features of gcc started to rely on the
strict-aliasing rule without taking -fno-strict-aliasing into
consideration. I didn't find anything in the bugzilla, but it's easy to
miss something as there are about 500 bugs opened about aliasing.

I'll open a bug about this.

>> This works when used in place of "struct sockaddr_storage".
>
> This might be something we can switch to in the future to see if we can
> remove -fno-strict-aliasing (but for how long?). The emitted code is
> slightly better without it (less data reloads) and disabling aliasing
> for the whole code just to satisfy a few places is a bit annoying.

We can keep the -fno-strict-aliasing but use the union to be more future
proof. After all, it would result in less undefined behavior. Basically,
it would be to turn all "struct sockaddr" and "struct sockaddr_storage"
to "struct sockaddr_any" which would be an anonymous union of "struct
sockaddr, struct sockaddr_in, struct sockaddr_in6, struct
sockaddr_storage". This may breaks some old code as I tend to remember
that at some point, "struct sockaddr" was not a "concrete" type (no
known size). If that's really important, we could exclude it from the
union and never use "sa_family" but "ss_family".

>> I see the
>> glibc is using an union too instead of struct sockaddr or struct
>> sockaddr_storage. man 7 socket still says to use struct
>> sockaddr_storage.
>
> Yes it depends a lot on the syscalls in fact :-/

On my system, I am refering to this header file:
 /usr/include/x86_64-linux-gnu/sys/socket.h

#v+
extern int accept (int __fd, __SOCKADDR_ARG __addr,
                   socklen_t *__restrict __addr_len);
#v-

And __SOCKADDR_ARG is the "universal" union.
-- 
O, it is excellent
To have a giant's strength; but it is tyrannous
To use it like a giant.
                -- Shakespeare, "Measure for Measure", II, 2

Reply via email to