[PATCH v2 00/25] Simplify inclusion conditionals

Andrew Clayton andrew at digital-domain.net
Mon Jun 20 14:32:31 UTC 2022


On Mon, 20 Jun 2022 13:36:00 +0100
Andrew Clayton <andrew at digital-domain.net> wrote:

> On Mon, 20 Jun 2022 13:28:41 +0100
> Andrew Clayton <andrew at digital-domain.net> wrote:
> 
> > But then I did a make clean and ./configure && make and all was good.  
> 
> Hmm, so taking my own advice, _now_ I see a load of errors... will
> investigate.

Not got right to the bottom of it, but here's where we're at.

The first error is

cc -c -pipe -fPIC -fvisibility=hidden -O -W -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wmissing-prototypes -Werror -g   -I src -I build   \
                      \
                     \
-o build/src/nxt_socketpair.o \
-MMD -MF build/src/nxt_socketpair.dep -MT build/src/nxt_socketpair.o \
src/nxt_socketpair.c
In file included from /usr/include/sys/socket.h:33,
                 from /usr/include/netinet/in.h:23,
                 from /usr/include/netdb.h:27,
                 from src/nxt_unix.h:157,
                 from src/nxt_main.h:31,
                 from src/nxt_socketpair.c:7:
src/nxt_socket_msg.h:32:54: error: invalid application of ‘sizeof’ to incomplete type ‘nxt_socket_cred_t’ {aka ‘struct ucred’}
   32 |     (CMSG_SPACE(2 * sizeof(int)) + CMSG_SPACE(sizeof(nxt_socket_cred_t)))
      |                                                      ^~~~~~~~~~~~~~~~~

On Linux/glibc at least, struct ucred is defined in
/usr/include/bits/socket.h as

#ifdef __USE_GNU                                                                
/* User visible structure for SCM_CREDENTIALS message */                        
struct ucred                                                                    
{                                                                               
  pid_t pid;                    /* PID of sending process.  */                  
  uid_t uid;                    /* UID of sending process.  */                  
  gid_t gid;                    /* GID of sending process.  */                  
};                                                                              
#endif

So it needs _GNU_SOURCE defined, as confirmed by this test case

#define _GNU_SOURCE 1                                                           
                                                                                
#include <sys/socket.h>                                                         
                                                                                
int main(void)                                                                  
{                                                                               
        sizeof(struct ucred);                                                   
        return 0;                                                               
}

Commenting out the #define makes it fail to compile.

$ make m
cc     m.c   -o m
m.c: In function ‘main’:
m.c:9:16: error: invalid application of ‘sizeof’ to incomplete type ‘struct ucred’
    9 |         sizeof(struct ucred);
      |                ^~~~~~
make: *** [<builtin>: m] Error 1

Now previously malloc.h was being included _after_ _GNU_SOURCE was being defined.
malloc.h seems to somehow be interfering with that, as demonstrated by

#include <malloc.h>                                                             
                                                                                
#define _GNU_SOURCE 1                                                           
                                                                                
#include <sys/socket.h>                                                         
                                                                                
int main(void)                                                                  
{                                                                               
        sizeof(struct ucred);                                                   
        return 0;                                                               
}


which fails to build.

Indeed if in unit, I comment out the malloc.h include, it builds, or if
I define _GNU_SOURCE before it, it builds.

Hmm, actually, including any system (at least) header file before
_GNU_SOURCE is defined breaks the test program.

Arghhhh....

Of course, all these header files include features.h which deals with
all the standards macros.

So if we include a header file before _GNU_SOURCE is defined, then
_FEATURES_H is defined, then if we define _GNU_SOURCE and include more
header files, then features.h won't do anything due to _FEATURES_H
already being defined and _GNU_SOURCE will have no effect as in
/usr/include/features.h

#ifdef  _GNU_SOURCE
# define __USE_GNU      1
#endif

won't happen. (__USE_GNU is what glibc seems to use internally for
_GNU_SOURCE).

OK, so not every header file includes features.h, for example
sys/syscall.h which is why things worked before.

So maybe we did get to the bottom of it...

So it just remains to see how to solve this current issue. But
basically you need to define _GNU_SOURCE before including any header
file that includes features.h.

Cheers,
Andrew



More information about the unit mailing list