Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SIG_IGN, SIG_DFL, SIG_ERR 's definition

Tags:

c

linux

signals

In <signal.h> there are definition of following:

#define SIG_ERR (void (*)())-1

#define SIG_DFL (void (*)())0

#define SIG_IGN (void (*)())1

I think void (*)() means it's a function pointer that return type is void and parameter is void(because there is empty between parenthesis).

But in signal() function, the second argument type is void (*func)(int).

Then, why the definition above three things are void (*)(). And, also, what means the number -1 0 1 in the definition?

How can I interpret these definitions?

like image 831
A.Cho Avatar asked Mar 06 '16 15:03

A.Cho


2 Answers

Your definitions are different from mine. If I preprocess the following file:

#include <signal.h>
SIG_IGN
SIG_DFL
SIG_ERR

The last 3 lines in the preprocessor output are

% gcc -E sigtest.c|tail -n3
((__sighandler_t) 1)
((__sighandler_t) 0)
((__sighandler_t) -1)

and the typedefs are

typedef __signalfn_t *__sighandler_t;

and

typedef void __signalfn_t(int);

from asm-generic/signal-defs.h. So it must be that you have some old headers.

However, this is not C++, but C. Empty parentheses in C mean that the function arguments are not declared / that the function can take any number of arguments. This has been considered obsolescent since C89 standard. Yet, a value of type void (*)() would be compatible with void (*)(int).


The values -1, 0 and 1 are non-portable magic constants that have meaning only to the Linux kernel.


How can I interpret these definitions?

#define SIG_DFL (void (*)()) 0 is merely an ordinary #define with casting.

You must know #define HAHA 2 (a int with value 2),
so what about #define HAHA (float) 2(a float with value 2) ,
and #define HAHA (int*) 2 (a pointer to int/int* with value(the pointer's value) 2).

So #define SIG_DFL (void (*)()) 0 means it's defining a (function) pointer, and the pointer's value is 0.

Again, SIG_DFL is a constant with value 2, and its type is void(*)(int), a (function) pointer.

As for function pointers, it's something you can call directly.

#include <stdio.h>

void foo(int a){
    printf("%d\n", a);
    printf("hahaha\n");
}

int main(){
    foo(3); //you can call foo() directly
    //or you may call it through a matched function pointer
    void (*foo_ptr)(int);   // I am declaring a function pointer
    foo_ptr =  foo;
    foo_ptr(3);  //same as calling foo(3)
}

Why the definition above three things are void (*)()?

Because it's what the signal function requires. The signal function requires its handlers to have function signature like void (*)(int).

So the fake functions (SIG_DFL, SIG_IGN) also need to be the void (*)(int) type.

Note the SIG_ERR is used to indicate a handler setting failure.

See the parameter description of handler from https://en.cppreference.com/w/c/program/signal.


What does the number -1 0 1 in the definition mean?

See What 's the meaning of the number 1 in SIG_IGN macro definition?


I have to say at first I was mainly stuck in the pattern #define SIG_DFL (void (*)()) 0, I didn't realize it is a casting.. :)

like image 30
Rick Avatar answered Oct 13 '22 21:10

Rick