Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

281
Vistas
hacer que open() regrese cuando se captura la señal

Cuando llamo a open("./fifo",O_RDONLY) , la llamada al sistema se bloqueará porque nadie está escribiendo en el fifo ./fifo . Si se recibe una señal durante ese tiempo que no tiene controlador de señal, el proceso finaliza instantáneamente. Hasta aquí todo bien. Pero cuando se recibe una señal que tiene un controlador de señal, el controlador de señal se ejecuta y la llamada al open() aún se bloquea.

¿Cómo puedo hacer que open() regrese cuando capto la señal?

Traté de bloquear la señal, eso no funciona porque no hay un argumento sigmask para open() como lo hay para pselect() . Usar O_NONBLOCK tampoco funciona, porque entonces open() regresará con un error, ya sea que haya una señal o no. Eliminar el controlador de señal tampoco es bueno porque quiero poder reaccionar a la señal.

Mi código de prueba:

 #include <errno.h> #include <fcntl.h> #include <signal.h> #include <stdbool.h> #include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> static volatile bool end=0; static void catchSignal(int signal) { (void)signal; const char *s="Catched Signal\n"; write(STDERR_FILENO,s,strlen(s)); end=1; } static int openFile(void) { int fd=open("./in",O_RDONLY); if(fd<0) { perror("can't open file"); exit(1); } return fd; } int main() { if(SIG_ERR==signal(SIGTERM,catchSignal)) { perror("cant set up signal handler"); return -1; } int fd = openFile(); while(end==0) { puts("Still running"); usleep(300UL*1000); } puts("End now"); if(fd>0) { close(fd); } return 0; }
over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

La función signal() es problemática debido a un historial de implementaciones con diferentes detalles. De acuerdo con su página de manual de Linux :

El único uso portátil de signal() es establecer la disposición de una señal en SIG_DFL o SIG_IGN . La semántica cuando se usa signal() para establecer un controlador de señal varía según los sistemas (y POSIX.1 permite explícitamente esta variación); no lo use para este propósito .

(Énfasis en el original)

En lugar de signal() , deberías usar sigaction() :

 struct sigaction sa = { .sa_handler = catchSignal }; if (SIG_ERR == sigaction(SIGTERM, &sa, NULL))

Tenga en cuenta que entre los campos de una struct sigaction se encuentra sa_flags , una máscara de bits con la que puede seleccionar entre los diversos comportamientos implementados históricamente por diferentes versiones de signal() . En particular, si no incluye el indicador SA_RESTART , ya que el anterior no lo hace, entonces no debería ver que las llamadas al sistema se reanudan automáticamente cuando son interrumpidas por una señal (excepto aquellas pocas que están explícitamente especificadas para hacerlo).

over 4 years ago · Santiago Trujillo Denunciar

0

Cuando strace su programa, ve que las funciones de señal () establecen el indicador SA_RESTART para la señal:

 rt_sigaction(SIGTERM, {sa_handler=0x562f2a8c3249, sa_mask=[TERM], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x7fb504d2d210}, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0

lo que significa que la llamada al sistema open() se reiniciará automáticamente después de manejar la señal.

Puede usar sigaction() para tener un control más detallado sobre el manejo de la señal y no configurar SA_RESTART:

 struct sigaction sa; memset (&sa, 0, sizeof (sa)); sa.sa_handler = catchSignal; sa.sa_flags = 0; sigemptyset (&sa.sa_mask); if (sigaction (SIGTERM, &sa, NULL) == -1) { perror("sigaction"); return -1; }
over 4 years ago · Santiago Trujillo Denunciar

0

puede usar O_NONBLOCK en cuyo caso open() regresará inmediatamente, y bloqueará tan pronto como fcntl(2) cancele O_NONBLOCK .

Lea la página de manual, ya que probablemente tenga alguna forma de hacer que open(2) devuelva -1 y errno igual a EINTR . Pero el uso normal es el que se ha descrito, la llamada se vuelve a emitir, por lo que el controlador de la señal no hace que la llamada se interrumpa (mucho del código depende de este comportamiento). No estoy seguro de esto, pero creo que solo pause(2) y select(2) y los amigos se interrumpen (y regresan) cuando se recibe una señal no ignorada.

Vale la pena señalar que solo el hilo que está bloqueado en una llamada interrumpible y recibe la señal se despierta y la llamada se interrumpe, y el hilo que recibe la interrupción puede ser cualquiera de los que haya iniciado en su proceso.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda