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?

4voto

fizzer Punkte 13343

In diesem speziellen Fall ist es nicht sicher, fclose() erneut aufzurufen, da der C-Standard besagt, dass der Stream von der Datei getrennt wird (und unbestimmt wird), selbst wenn der Aufruf fehlschlägt.

3voto

Verwenden Sie eine Struktur von Funktionszeigern, um die Systemfunktionen zu abstrahieren. Ersetzen Sie den Aufruf von flcose(fp) durch etwas wie sys->fclose(fp). Erstellen Sie in Ihrem Unit-Test eine Implementierung von fclose, die immer EINTR zurückgibt, und setzen Sie sys->fclose auf diese Version.

3voto

bmdhacks Punkte 15405

Wenn ich mir den Quellcode des Linux-Kernels ansehe, kann ich keinen Treiber finden, der beim Schließen einer Datei EINTR zurückgibt.

Wenn Sie diesen Fall absosmurfly reproduzieren müssten, könnten Sie Ihren eigenen Treiber in Linux schreiben, um -EINTR bei der .release-Methode zurückzugeben. Werfen Sie einen Blick auf die Beispielcode aus dem Buch Linux Device Drivers von O'Reilly. Das scull-Projekt ist eines der einfachsten Projekte. Sie würden es so ändern, dass es wie folgt aussieht:

int scull_release(struct inode *inode, struct file *filp)
{
    return -EINTR;
}

Aber auch hier kann ich beim Durchstöbern des Linux-Quellbaums keinen Treiber finden, der beim Schließen EINTR zurückgibt.

EDIT - ok es sieht so aus, als ob fuse - das Userspace-Dateisystem dazu in der Lage sein könnte. Dies wird für Dinge wie sshfs verwendet. Es ist aber immer noch ein Grenzfall.

2voto

Benoit Punkte 36144

Ich glaube nicht, dass es eine einfache Möglichkeit gibt, dies nach Belieben zu testen.

EINTR wird erzeugt, wenn die Operation fclose durch ein Signal unterbrochen wird. Dies bedeutet, dass fclose in einem Hintergrund-Thread war, der ein Signal erhielt, als er die Schließanforderung verarbeitete.

Viel Glück bei dem Versuch, diese Umstände zu reproduzieren.

1voto

mhawke Punkte 79590

Wie Kris vorschlägt, ersetzen Sie vorübergehend Anrufe bei der "echten" fclose() mit Ihrer eigenen Implementierung, die in Ihrem Unit-Test-Code definiert ist. Ihre Implementierung könnte etwas so Einfaches tun wie:

int my_fclose(FILE *fp)
{
  errno = EINTR;
  return EOF;
}

Aber, wie fizzer anmerkt, sollten Sie nicht fclose() wieder, da das Verhalten undefiniert ist, so dass Sie sich nicht einmal die Mühe machen müssen, die Bedingung zu überprüfen.

Die andere Frage, die man sich stellen muss, ist, ob man sich darüber wirklich Sorgen machen muss; wenn Ihr Anwendungscode alle möglichen Signale (außer SIGKILL und SIGSTOP) während Ihrer fclose() dann würden Sie kein EINTR erhalten und bräuchten sich keine Sorgen zu machen.

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