Search code examples
linuxsolarissignalsc99

SA_RESTART not defined under Linux, compiles fine in Solaris


Disclaimer: This is for a programming class, but it is not the answer or purpose of the assignment.

We have access to multiple *nix-like servers in my university, and are encouraged to compile our projects on each of them to see how different environments change things. I'm currently doing a project that involves signals and I've hit a difference that I cannot fix myself.

Under a Solaris based server, everything works:

xxxxxxx@xxx:~/proj6$ make gcc-new
rm -f ./pr6
gcc -std=c99 -Wall -Wextra -D_POSIX_C_SOURCE=200112L -D_POSIX_PTHREAD_SEMANTICS -o pr6 pr6.2.c pr6_ctime.c pr6_signal.c
 pr6_signal.c:64: warning: unused parameter 'sig'
 pr6_signal.c:64: warning: unused parameter 'func'

Under a Linux based server, I see this:

xxxxxxx@xxxxx:~/proj6$ make gcc-new
rm -f ./pr6
gcc -std=c99 -Wall -Wextra -D_POSIX_C_SOURCE=200112L -D_POSIX_PTHREAD_SEMANTICS  -o pr6  pr6.2.c pr6_ctime.c pr6_signal.c
pr6_signal.c: In function âinstall_signal_handlerâ:
pr6_signal.c:45: error: âSA_RESTARTâ undeclared (first use in this function)
pr6_signal.c:45: error: (Each undeclared identifier is reported only once
pr6_signal.c:45: error: for each function it appears in.)
pr6_signal.c: In function âreinstall_signal_handlerâ:
pr6_signal.c:64: warning: unused parameter âsigâ
pr6_signal.c:64: warning: unused parameter âfuncâ
make: *** [gcc-new] Error 1

I've fiddled around with different combinations of c99, POSIX 2001-12, and POSIX pthread to no avail. I don't understand why it is that SA_RESTART would not be defined under Linux as it is part of the POSIX standard and I've included that flag on GCC. If I forgot to #include something then it should be absent on both systems, no?

UPDATE:

I used gcc -M to determine which files are included in my compile on each machine and then used grep to try to find the definition. So far these are my results:

(On Solaris)

xxxxxxx@xxx:~/proj6$ grep "SA_RESTART" /usr/include/sys/signal.h
#define SA_RESTART      0x000004
xxxxxxx@xxx:~/proj6$ grep "SA_RESTART" ./linux-signal.h
xxxxxxx@xxx:~/proj6$



xxxxxxx@xxx:~/proj6$ grep "#include" ./linux-signal.h
#include <features.h>
#include <bits/sigset.h>                /* __sigset_t, __sig_atomic_t.  */
#include <bits/types.h>
#include <bits/signum.h>
xxxxxxx@xxx:~/proj6$ grep "#include" /usr/include/sys/signal.h
#include <sys/feature_tests.h>
#include <sys/iso/signal_iso.h>
#include <sys/siginfo.h>
#include <sys/ucontext.h>
#include <sys/t_lock.h>

(On Linux)

xxxxxxx@xxxxx:~/proj6$ grep "SA_RESTART" /usr/include/features.h
xxxxxxx@xxxxx:~/proj6$ grep "SA_RESTART" /usr/include/bits/sigset.h 
xxxxxxx@xxxxx:~/proj6$ grep "SA_RESTART" /usr/include/bits/types.h
xxxxxxx@xxxxx:~/proj6$ grep "SA_RESTART" /usr/include/bits/signum.h
xxxxxxx@xxxxx:~/proj6$

So there is no definition for SA_RESTART in any of the files being included under Linux (the compiler told me this to start with) so the question is WHY?

Update #2: contents of /usr/include/sys/signal.h on Linux is just `#include

Update #3: output of grep -r SA_RESTART /usr/include

/usr/include/bits/sigaction.h:# define SA_RESTART   0x10000000 /* Restart syscall on signal return.  */
/usr/include/asm-generic/signal.h: * SA_RESTART flag to get restarting signals (which were the default long ago)
/usr/include/asm-generic/signal.h:#define SA_RESTART    0x10000000
Binary file /usr/include/c++/3.4.6/x86_64-redhat-linux/bits/stdc++.h.gch/O2g matches
Binary file /usr/include/c++/3.4.6/x86_64-redhat-linux/bits/stdc++.h.gch/O0g matches
/usr/include/mysql/my_pthread.h:  as Mac OS X, sigset() results in flags such as SA_RESTART being set, and
/usr/include/asm/signal.h: * SA_RESTART flag to get restarting signals (which were the default long ago)
/usr/include/asm/signal.h:#define SA_RESTART    0x10000000u
grep: warning: /usr/include/gphoto2/gphoto2: recursive directory loop

/usr/include/valgrind/vki/vki-ppc64-linux.h:#define VKI_SA_RESTART      0x10000000u
/usr/include/valgrind/vki/vki-darwin.h:#define VKI_SA_RESTART   SA_RESTART
/usr/include/valgrind/vki/vki-ppc32-linux.h:#define VKI_SA_RESTART              0x10000000
/usr/include/valgrind/vki/vki-x86-linux.h:#define VKI_SA_RESTART                0x10000000u
/usr/include/valgrind/vki/vki-s390x-linux.h: * SA_RESTART flag to get restarting signals (which were the default long ago)
/usr/include/valgrind/vki/vki-s390x-linux.h:#define VKI_SA_RESTART      0x10000000
/usr/include/valgrind/vki/vki-amd64-linux.h:#define VKI_SA_RESTART              0x10000000
/usr/include/valgrind/vki/vki-arm-linux.h:#define VKI_SA_RESTART                0x10000000u

So it resides in a file called sigaction.h (which makes sense) and that file is being included (verified with gcc -M), so why is the compiler complaining?


Solution

  • It's due to your -D flag:

    #include <signal.h>
    #include <stdio.h>
    
    int main(void) {
    #ifdef SA_RESTART
        puts("have SA_RESTART");
    #else
        puts("no SA_RESTART");
    #endif
        return 0;
    }
    
    $ cc foo.c && ./a.out
    have SA_RESTART
    $ gcc -std=c99 -Wall -Wextra -D_POSIX_C_SOURCE=200112L -D_POSIX_PTHREAD_SEMANTICS foo.c && ./a.out
    no SA_RESTART
    $ gcc -std=c99 -Wall -Wextra -D_POSIX_C_SOURCE=200809L -D_POSIX_PTHREAD_SEMANTICS foo.c && ./a.out
    have SA_RESTART
    

    In particular, "200112L" means "don't give me SA_RESTART". See /usr/include/features.h.

    Edit: as Andrew Henle notes in a comment, this particular Linux features.h is (or was back in 2012) just plain wrong here: see the SUS spec from 1997. Still, if it's wrong in whatever system you're using, you may need to work around that.