Search code examples
clinuxprocesssignalssigaction

How to set more than one flag in sigaction.sa_flags


I have the following structure:

struct sigaction sa1;
sa1.sa_flags=SA_SIGINFO;
sa1.sa_flags=SA_NODEFER;
sa1.sa_sigaction = handler;
sigaction(SIGUSR1,&sa1,NULL);

How can I use SA_SIGINFO along with SA_NODEFER without making the second flag overrides the first?


Solution

  • The manual page has the answer:

    It is formed by the bitwise OR of zero or more of the following: [...]

    So you'd do something like

    sa1.sa_flags = SA_NODEFER | SA_SIGINFO;
    

    This way of representing multiple independent flags as single bits in an integer is very very common in all of programming, and certainly in C. It's easily available since bitwise manipulation is simple in C, and often desirable since it's a very light implementation.

    A more "modern" (verbose, and/or Bloaty McBloatface) approach might be to use bitfields in a structure:

    struct sigaction {
      /* ... */
      struct {
        unsigned int sa_nocldstop : 1;
        unsigned int sa_nocldwait : 1;
        unsigned int sa_nodefer : 1;
        unsigned int sa_nostack : 1;
        unsigned int sa_siginfo : 1;
        /* ... */
      } sa_flags;
      /* ... */
    };
    

    This makes the sa_flags member in struct sigaction itself be a struct, which consists of a bunch of 1-bit wide unsigned int members. This will typically compile down to the exact same bitwise code, but it's more clear.

    You'd set multiple flags by doing explicit sets:

    sa1.sa_flags.sa_nodefer = 1;
    sa1.sa_flags.sa_siginfo = 1;
    

    and you'd need some other way to make sure the rest got set to 0.