Unterbrechen des blockierten Lesens

Lesezeit: 2 Minuten

Mein Programm durchläuft eine Schleife wie diese:

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

Die Lesefunktion blockiert, wenn sie auf eine Eingabe wartet, die zufällig von einem Socket stammt. Ich möchte mit SIGINT umgehen und es im Grunde anweisen, die Lesefunktion zu stoppen, wenn es liest, und dann eine beliebige Funktion aufzurufen. Was ist der beste Weg, dies zu tun?

Benutzeravatar von sarnold
Sarnold

Aus read(2):

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

Wenn Sie Ihren Code so ändern, dass er eher so aussieht:

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

Dies lässt arbitrary_function() entscheiden, ob die read(2) erneut versucht werden soll oder nicht.

Aktualisieren

Sie müssen das Signal verarbeiten, um das zu erhalten EINTR Verhalten ab 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;
}

Gibt Ausgabe:

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

  • Mit dem, was Sie bereitgestellt haben, beendet das Senden von SIGINT (über Strg + C) nur das Programm.

    – Kaykun

    6. Juni 2011 um 9:06 Uhr


  • @kaykun, nur wenn das die letzte Zeile im Programm ist. Sie könnten nach dem weitere Zeilen hinzufügen while blockieren, die die Übertragung neu starten, Sie könnten diesen bestimmten Client löschen und mit der Hauptschleife Ihres Programms fortfahren, Sie könnten eine interaktive Shell mit dem Benutzer starten, um zu fragen, welche Aktionen als nächstes ausgeführt werden sollen … nichts sagt, dass dies beendet werden muss Programm.

    – Sarnold

    6. Juni 2011 um 9:13 Uhr

  • @sarnold Falsch, zumindest für mich wird das Programm beendet, wenn SIGINT gesendet wird, egal was ich nach der While-Schleife hinzufüge, was auch für fast alle anderen Befehlszeilenprogramme gilt.

    – Kaykun

    6. Juni 2011 um 9:21 Uhr


  • Wenn Sie sigaction verwenden, wie Sie es mit SIG_IGN beschrieben haben, bewirkt Strg + C nur nichts; Lesen Sie noch Blöcke. Sie können selbst überprüfen: pastebin.com/ybVt79tQ

    – Kaykun

    6. Juni 2011 um 9:47 Uhr

  • handle_int(int num) muss den Typ für den Parameter angeben. Leider ist die Bearbeitungswarteschlange für diese Antwort voll …

    – dunkler Drache

    19. Oktober um 16:25 Uhr

Wenn Ihr Prozess ein Signal empfängt, read() wird zurückkehren und der Wert von errno wird eingestellt EINTR.

1433080cookie-checkUnterbrechen des blockierten Lesens

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy