Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

279
Views
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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!