Publi

Conociendo el proceso que me ha enviado una señal (signal)

Hace tiempo hablábamos de capturar señales, aunque en ocasiones, es necesario saber quién me envía esa señal, si por ejemplo nos envían un SIGINT o SIGTERM, tal vez queremos saber qué proceso nos quiere muerto y qué usuario lo ha invocado. O tal vez estamos esperando una señal de control (SIGUSR1, por ejemplo) por parte de un proceso cliente específico.

El problema es que por nuestro modo actual de direccionar señales (con signal(señal, funcion)) sólo comunicamos el número de señal que se ha recibido, sin más información.

signals_from

Para capturar esta información necesitamos utilizar sigaction para establecer la función a la que llamaremos cuando llegue la señal, para utilizarla podemos utilizar el siguiente código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

void recibe_signal(int signum, siginfo_t *siginfo, void *context)
{
  /* Mostramos toda la información necesaria */
  printf ("[%d] Recibida %d (%s) de %d (UID: %d) ¿Error? %d \n",
      getpid(),
      signum,
      strsignal(signum),
      siginfo->si_pid,
      siginfo->si_uid,
      siginfo->si_errno);
}


int main(int argc, char *argv[])
{
    struct sigaction sact;
   
    sigfillset(&sact.sa_mask);
    /* Definimos la función callback */
    sact.sa_sigaction = recibe_signal;
    /* Queremos usar el callback sigaction en lugar del dado por signal() */
    sact.sa_flags     = SA_SIGINFO;

    sigaction(SIGUSR1, &sact, NULL);

    /* Bucle infinito, para cerrar el proceso, utilizar kill -9 PID */
    while (1)
      pause;

    return 0;
}

Como vemos sigaction tiene 3 parámetros:

  • La señal que queremos capturar
  • Un registro de tipo struct sigaction
  • La acción que se ejecutaba antes, por si queremos guardarla para restaurarla más tarde

Dentro del registro, tendremos como valores importantes (struct sigaction act):

  • sact.sa_sigaction : que especifica la función que la llamaremos, esta función será del tipo void funcion(int, siginfo_t*, void*), donde el primer int recibirá la señal que nos han enviado (tal y como hacía la función que asignábamos con signal), el segundo parámetro será información asociada a la señal, y la tercera el contexto de ejecución.
  • sact.sa_handler : será la función a la que se llama, es la misma que cuando hacemos signal(señal, funcion)
  • sact.sa_flags : Es un conjunto de flags, si especificamos SA_SIGINFO, estaremos dando paso a la función especificada por sa_sigaction, si no utilizaremos sa_handler. Aunque esta variable vale para más cosas, para esta práctica nos vale con saber esto. (man sigaction para más info)
  • sact.sa_mask
  • : Nos proporciona una máscara de las señales que serán bloquedas, podemos utilizar sigfillset() para rellenar toda la máscara automáticamente. Si queremos que unas se bloqueen y otras no podemos utilizar sigaddset() y sigdelset()

Ahora bien, la función que se llamará cuando venga una señal tendrá el prototipo que hemos visto antes con tres parámetros: la señal recibida, la información de la señal con un puntero a siginfo_t y el contexto de ejecución, que se pasará con un puntero a void, que por ahora no utilizaremos. La estructura que controla la información de la señal entre otros muchos datos nos facilitará lo siguiente:

  • si_pid : PID que nos envía la señal (y esta acción da título al post)
  • si_uid : Usuario que ejecuta el proceso que nos manda la señal
  • si_errno : Algún error que haya causado la señal
  • … para más información, man sigaction

Para preparar la sentencia tendremos que escribir varias líneas definiendo los valores del registro así como la llamada a la función sigaction(), por lo tanto podremos crear una función que tenga los parámetros más comunes a la hora de definir este tipo de acciones, así lo llamamos como a signal():

1
2
3
4
5
6
7
8
9
10
11
12
int sigact(int signum, void funcion(int, siginfo_t *, void *))
{
    struct sigaction sact;
   
    sigfillset(&sact.sa_mask);
    /* Definimos la función callback */
    sact.sa_sigaction = funcion;
    /* Queremos usar el callback sigaction en lugar del dado por signal() */
    sact.sa_flags     = SA_SIGINFO;

    return sigaction(signum, &sact, NULL);
}

En esta función es importante poner bien el prototipo de la función como parámetro, eso lo comenté en un post anterior sobre callbacks

Ahora, vamos a dejar el código más bonito, este programa implementará el control de errores y nos permitirá salir cuando recibamos 5 SIGINT (pulsemos 5 veces control+C):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

void error(char *cadena);
int sigact(int signum, void funcion(int, siginfo_t *, void *));
void llegasigint();
void recibe_signal(int signum, siginfo_t *siginfo, void *context);

int main(int argc, char *argv[])
{
  if (sigact(SIGUSR1, recibe_signal)==-1)
    error("No puedo establecer SIGUSR1");

  if (sigact(SIGINT, recibe_signal)==-1)
    error("No puedo establecer SIGINT");
  if (sigact(SIGTERM, recibe_signal)==-1)
    error("No puedo establecer SIGTERM");
  if (sigact(SIGUSR2, recibe_signal)==-1)
    error("No puedo establecer SIGUSR2");
  if (sigact(SIGQUIT, recibe_signal)==-1)
    error("No puedo establecer SIGQUIT");

    /* Bucle infinito, para cerrar el proceso, utilizar kill -9 PID */
    while (1)
      pause();

    return 0;
}

void error(char *cadena)
{
  fprintf(stderr, "ERROR: %s (errno: %d: %s)\n", cadena, errno, strerror(errno));
  exit(1);
}

void llegasigint()
{
  static int num=0;     /* No he querido usar variables globales */

  num++;
  if (num==5)
    {
      printf ("FIN del programa\n");
      exit(1);
    }
}

void recibe_signal(int signum, siginfo_t *siginfo, void *context)
{
  /* Mostramos toda la información necesaria */
  printf ("[%d] Recibida %d (%s) de %d (UID: %d) ¿Error? %d \n",
      getpid(),     /* PID del proceso actual */
      signum,       /* Número de señal recibida */
      strsignal(signum),    /* Señal escrita en texto (inglés) */
      siginfo->si_pid,  /* PID del proceso que nos manda la señal */
      siginfo->si_uid,  /* Usuario que nos manda la señal */
      siginfo->si_errno);   /* Error producido */

  if (signum==SIGINT)
    llegasigint();
}

int sigact(int signum, void funcion(int, siginfo_t *, void *))
{
    struct sigaction sact;
   
    sigfillset(&sact.sa_mask);
    /* Definimos la función callback */
    sact.sa_sigaction = funcion;
    /* Queremos usar el callback sigaction en lugar del dado por signal() */
    sact.sa_flags     = SA_SIGINFO;

    return sigaction(signum, &sact, NULL);
}

También podría interesarte....

There are 20 comments left Ir a comentario

  1. Pingback: Bitacoras.com /

  2. Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    it’s really attractive and even meanful. it’s really nice web log. Associating is amazingly invaluable item. you have got certainly given a hand to plenty of people just who have a look at web log and allow them all usefull tips.

  3. Usando Google Chrome Google Chrome 119.0.0.0 en Windows Windows NT

    This is definitely the knowledge We are acquiring all over the place. Cheers for ones web site, I merely join your blog. This is the wonderful web site

  4. yitzchak kerrigan /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    The audio will be awesome. You might have several extremely skilled performers. My partner and i want an individual the most effective regarding accomplishment. ultra panda mobi

  5. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    TrustSpot Playground: Dive into a secure gaming adventure at TrustSpot Playground. Rigorously screened for fraud, this Toto site guarantees safety. Backed by a robust operational track record, substantial capital, and swift withdrawals, your peace of mind is our priority. 안전놀이터

  6. mehmood alam /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    It is a great website.. The Design looks very good.. Keep working like that!. โปรโมชั่น ufabet

  7. seooo servicesss /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    I appreciated your work very thanks ufabet.com ทางเข้า

  8. sfgfgfdgfgsf /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Thanks for your post. I’ve been thinking about writing a very comparable post over the last couple of weeks, I’ll probably keep it short and sweet and link to this instead if thats cool. Thanks. ufabet.com ทางเข้า มือถือ

  9. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    The writer has outdone himself this time. It is not at all enough; the website is also utmost perfect. I will never forget to visit your site again and again. 강남 룸

  10. MUZAMMIL SEO MUZAMMIL SEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Great knowledge, do anyone mind merely reference back to it 홍대룸싸롱

  11. MUZAMMIL SEO MUZAMMIL SEO /
    Usando Google Chrome Google Chrome 120.0.0.0 en Windows Windows NT

    Awesome article! I want people to know just how good this information is in your article. It’s interesting, compelling content. Your views are much like my own concerning this subject. 우리카지노

  12. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Yes, I am entirely agreed with this article, and I just want say that this article is very helpful and enlightening. I also have some precious piece of concerned info !!!!!!Thanks. 신촌고수익알바

  13. MUZAMMIL SEO MUZAMMIL SEO /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    This is truly a great read for me. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work!. Casselberry personal trainer

  14. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    This is a great post. I like this topic.This site has lots of advantage.I found many interesting things from this site. It helps me in many ways.Thanks for posting this again. router

  15. seooo servicesss /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    If more people that write articles really concerned themselves with writing great content like you, more readers would be interested in their writings. Thank you for caring about your content. buy ambien online

  16. MUZAMMIL SEO MUZAMMIL SEO /
    Usando Google Chrome Google Chrome 121.0.0.0 en Windows Windows NT

    Join PLAYSBO for an elite online football betting adventure! Enjoy quick service, fair play, and exclusive promotions that set us apart. Trust us for seamless transactions and unbeatable satisfaction in the world of online betting. sbobet88

  17. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    Positive site, where did u come up with the information on this posting? I’m pleased I discovered it though, ill be checking back soon to find out what additional posts you include. tdtc

  18. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    I think this is an informative post and it is very useful and knowledgeable. therefore, I would like to thank you for the efforts you have made in writing this article. 토토사이트 추천

  19. MUZAMMIL SEO MUZAMMIL SEO /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    Very interesting blog. Alot of blogs I see these days don’t really provide anything that I’m interested in, but I’m most definately interested in this one. Just thought that I would post and let you know. https://www.bsc.news/post/8-andab-ewbsl-t-opromchan-9rab100-r-ngrab-w-elth-thiiniymmaakthiisud-ainpii-2024

  20. ALEXENDER RAVI /
    Usando Google Chrome Google Chrome 122.0.0.0 en Windows Windows NT

    I read that Post and got it fine and informative. https://www.bsc.news/post/10-andab-ewbsl-t-opromchan-10rab100-thiiniymmaakthiisud-ainpii-2024

Leave a Reply