Interrumpir lectura bloqueada

2 minutos de lectura

Mi programa pasa por un bucle como este:

...
while(1){
  read(sockfd,buf,sizeof(buf));
  ...
}

La función de lectura se bloquea cuando está esperando una entrada, que resulta ser de un zócalo. Quiero manejar SIGINT y básicamente decirle que detenga la función de lectura si está leyendo y luego llamar a una función arbitraria. ¿Cuál es la mejor manera de hacer esto?

avatar de usuario de sarnold
Sarnold

De read(2):

   EINTR  The call was interrupted by a signal before any data
          was read; see signal(7).

Si modifica su código para que se parezca más a:

cont = 1;
while (1 && cont) {
    ret = read(sockfd, buf, sizeof(buf));
    if (ret < 0 && errno == EINTR)
        cont = arbitrary_function();
}

esto permite arbitrary_function() decidir si el read(2) se debe volver a intentar o no.

Actualizar

Necesita manejar la señal para obtener la EINTR comportamiento de read(2):

#include<unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<errno.h>

int interrupted;

void handle_int(int num) {
  interrupted = 1;
}

int main(void){
  char buf[9001];
  struct sigaction int_handler = {.sa_handler=handle_int};
  sigaction(SIGINT,&int_handler,0);
  while(!interrupted){
    printf("interrupted: %d\n", interrupted);
    if(read(0,buf,sizeof(buf))<0){
      if(errno==EINTR){
        puts("eintr");
      }else{
        printf("%d\n",errno);
      }
      puts(".");
    }
  }
  puts("end");
  return 0;
}

Da salida:

$ ./foo
interrupted: 0
hello
interrupted: 0
^Ceintr
.
end

  • Con lo que ha proporcionado, enviar SIGINT (a través de Ctrl+C) simplemente finaliza el programa.

    – kaykun

    6 de junio de 2011 a las 9:06


  • @kaykun, solo si esa es la última línea del programa. Podría agregar más líneas después de la while bloque que reinicia la transmisión, puede eliminar ese cliente específico y continuar con el bucle principal de su programa, puede iniciar un shell interactivo con el usuario para preguntar qué acciones tomar a continuación… nada dice que esto tiene que terminar el programa.

    – Sarnold

    6 de junio de 2011 a las 9:13

  • @sarnold Incorrecto, al menos para mí, el programa finaliza cuando se envía SIGINT sin importar lo que agregue después del ciclo while, que es lo mismo para casi todos los demás programas de línea de comandos.

    – kaykun

    6 de junio de 2011 a las 9:21


  • Usar sigaction como lo describiste con SIG_IGN solo hace que Ctrl+C no haga nada; leer bloques inmóviles. Puedes comprobarlo por ti mismo: pastebin.com/ybVt79tQ

    – kaykun

    6 de junio de 2011 a las 9:47

  • handle_int(int num) necesita especificar el tipo para el parámetro. Desafortunadamente, la cola de edición está llena para esta respuesta…

    – Dragón oscuro

    19 oct a las 16:25

Cuando su proceso recibe una señal, read() volverá y el valor de errno se establecerá en EINTR.

¿Ha sido útil esta solución?