2016-06-18 7 views
1

Ich möchte alarm() verwenden, um das Timeout von recvfrom festzulegen. Aber festgestellt, dass, wenn signal() verwenden, um einen Handler für SIGALRM zu registrieren, und eine SIGALRM wurde erfasst und dann den Signalhandler aufgerufen. Aber nach der Rückkehr von Handler, blockiert die recvfrom() immer noch, während keine Daten kommen und es keine EINTR Fehler gibt. Warum? Setzt das signal() das SA_RESTART Flag automatisch? Hier ist der Code:Warum recvfrom() blockiert immer noch, wenn ein SIGALRM erfasst wurde?

signal(SIGALRM, sig_handler); 
while(1) 
{ 
    alarm(5); 
    n = recvfrom(sock, buf, BUF_MAX, 0, (struct sockaddr*)&addr, &len); 
    if(n < 0) 
    { 
     if(errno == EINTR) 
     { 
      printf("recvfrom timeout\n"); 
      continue; 
     } 
     else 
     { 
      printf("recvfrom error\n"); 
     } 
    } 
    else 
    { 
     printf("data: %s\n", buf); 
     alarm(0); 
    } 
} 

void sig_handler(int signo) 
{ 
    return; 
} 
+0

Die eigentliche Frage ist, warum verwenden Sie nicht SO_RCVTIMEO? – EJP

Antwort

1

Ob der blockierenden Aufruf neu gestartet wird ein plattformabhängige Attribut ist nach signal ‚s Manpage:

Die Situation auf Linux ist wie folgt:

  • Der signal() - Systemaufruf des Kernels liefert System V-Semantik.
  • Standardmäßig ruft die signal() - Wrapperfunktion in glibc 2 und höher nicht den Kernel-Systemaufruf auf. Stattdessen ruft es sigaction (2) unter Verwendung von Flags auf, die BSD Semantik liefern. Dieses Standardverhalten wird bereitgestellt, sofern ein geeignetes Feature-Testmakro definiert ist: _BSD_SOURCE in glibc 2.19 und früher oder _DEFAULT_SOURCE in glibc 2.19 und höher. (Diese Makros sind standardmäßig definiert; Einzelheiten finden Sie unter feature_test_macros (7).) Wenn ein solches Feature-Testmakro nicht definiert ist, liefert signal() System V-Semantik.

Da BSD Semantik äquivalent sind mit den folgenden Flags zu nennen sigaction(2):

sa.sa_flags = SA_RESTART; 

und System V Semantik nicht SA_RESTART tut, was haben Sie, dass Ihr Programm die BSD Art und Weise tut, Sie sollten also die genannten Feature-Test-Makros verwenden, um das Verhalten Ihres Programms zu definieren.