7 Stimmen

Fehlerbedingungen für Einheitstests - EINTR

Kurz gesagt, wie testet man eine Fehlerbedingung wie EINTR bei einem Systemaufruf.

Ein spezielles Beispiel, an dem ich arbeite und das ein Fall für sich sein könnte, ist die Frage, ob es notwendig ist, fclose erneut aufzurufen, wenn es EOF mit (errno==EINTR) zurückgibt. Das Verhalten hängt von der Implementierung von fclose ab:

// Given an open FILE *fp
while (fclose(fp)==EOF && errno==EINTR) {
    errno = 0;
}

Dieser Aufruf kann unsicher sein, wenn fp beim Auftreten von EINTR freigegeben wird. Wie kann ich die Fehlerbehandlung für den Fall (errno==EINTR) testen?

1voto

philant Punkte 32877

Hier ist, wie ich es testen würde, nur um des Testens willen, da fizzer uns daran erinnert hat fclose() zweimal ist unsicher.

Es ist möglich neu definieren fclose() (oder eine andere Funktion der libc) in Ihrem Programm mit Ihrem eigenen Verhalten . Auf Unix-ähnlichen Systemen beschwert sich der Linker nicht - unter Windows habe ich es nie versucht, aber mit cygwin. Natürlich verhindert dies, dass Ihre anderen Tests den echten fclose() Daher muss ein solcher Test in einer separaten ausführbaren Testdatei gespeichert werden.

Hier ein umfassendes Beispiel mit Minieinheit .

#include <errno.h>
#include <stdio.h>
#include <stdbool.h>

/* from minunit.h : http://www.jera.com/techinfo/jtns/jtn002.html */
 #define mu_assert(message, test) do { if (!(test)) return message; } while (0)
 #define mu_run_test(test) do { char *message = test(); tests_run++; \
                                if (message) return message; } while (0)

int tests_run = 0;
bool fclose_shall_fail_on_EINTR = false;

//--- our implemention of fclose()
int fclose(FILE *fp) {
    if (fclose_shall_fail_on_EINTR) {
        errno = EINTR;
        fclose_shall_fail_on_EINTR = false;   //--- reset for next call 
        return EOF;
    } else { return 0; }
}

//--- this is the "production" function to be tested 
void uninterruptible_close(FILE *fp) {
    // Given an open FILE *fp
     while (fclose(fp)==EOF && errno==EINTR) {
        errno = 0;
     }
}

char *test_non_interrupted_fclose(void) {
    FILE *theHandle = NULL;   //--- don't care here
    uninterruptible_close(theHandle);
    mu_assert("test fclose wo/ interruption", 0 == errno);
    return 0;
}

char *test_interrupted_fclose(void) {
    FILE *theHandle = NULL;   //--- don't care here
    fclose_shall_fail_on_EINTR = true;

    uninterruptible_close(theHandle);
    mu_assert("test fclose wo/ interruption", 0 == errno);
    return 0;
}

char *test_suite(void)
{
    mu_run_test(test_non_interrupted_fclose);
    mu_run_test(test_interrupted_fclose);
    return 0;
}

int main(int ac, char **av)
{
  char *result = test_suite();

  printf("number of tests run: %d\n", tests_run);
  if (result) { printf("FAIL: %s\n", result); } 

  return 0 != result;
}

1voto

Ich glaube, Sie alle übersehen etwas sehr Wichtiges.

fclose() kann nicht EINTR zurückgeben. Ebenso wenig können fopen(), fwrite(), fread() oder andere C-Standard-E/A-Funktionen EINTR zurückgeben.

Nur wenn Sie sich mit den Low-Level-E/A-Aufrufen wie open(2), write(2) und select(2) beschäftigen, müssen Sie EINTR behandeln.

Lesen Sie die [lustigen] Manualseiten

1voto

Taher Hassan Punkte 9

Ich denke, dass es ein Problem mit der gleichzeitigen Verarbeitung von Signalen und der Bestätigung von Fehlerbedingungen geben könnte.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X