2017-11-15 1 views
2

Ich versuche, eine E-Mail mit sendmail in einem separaten pthread zu senden. Dieser Code funktioniert in 99,9% der Fälle.C++: Aufruf sendmail von Pthread Ergebnisse in Broken Pipe

void* emailClientThreadFct(void* emailClientPtr) 
{ 
    EmailClient* emailClient = static_cast<EmailClient*>(emailClientPtr); 

    try 
    { 
     emailClient->Send(); 
    } 
    catch (const exception& excep) 
    { 
     SYSLOG_ERROR("E-mail client exception: %s", excep.what()); 
    } 

    delete emailClient; 
    return NULL; 
} 

// Send email for current output in a separate thread 
pthread_t emailThread; 
pthread_attr_t attr; 

/* Initialize and set thread detached attribute */ 
pthread_attr_init(&attr); 
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 

pthread_create(&emailThread, &attr, emailClientThreadFct, emailClientObj); 

0,1% der Zeit, erhalte ich die Fehler fwrite error Broken Pipe, wenn ich den folgenden Aufruf tun. Von dem, was ich gelesen habe, ist Broken Pipe (EPIPE 32) normalerweise ein Empfängerproblem, aber Sendmail ist ein lokaler Prozess ... Könnte es sein, dass ich zu viele Daten an fwrite sende? Oder dass ich etwas Schlechtes in meiner Pthread-Instanziierung mache? Oder ist sendmail abgestürzt?

void EmailClient::Send() const 
{ 
    // Flush all open output streams, as recommended by popen man page 
    fflush(NULL); 

    string popen_command = "sendmail -t -oi >/dev/null 2>&1"); 

    // Open pipe to Mail Transport Agent (MTA) 
    errno = 0; 
    FILE* stream = popen(popen_command.c_str(), "w"); 

    if (stream == NULL) 
    { 
     throw exception("Cannot send email popen"); 
    } 
    errno = 0; 
    if (fwrite(message.data(), message.size(), 1, stream) < 1) 
    { 
     pclose(stream); 
     throw exception("fwrite error ", strerror(errno)); 
    } 

    // Close MTA 
    errno = 0; 
    if (pclose(stream) == -1) 
     printf("\"Error closing the MTA pipe (%s)\"", strerror(errno)) 
} 

Antwort

0

EPIPE bedeutet, dass das andere Ende (der Prozess, den Sie schreiben) gestorben ist. Dies kann passieren, wenn ein Fork-Fehler auftritt (popen ruft die Shell auf, sodass ein anderer Subprozess involviert ist), da vorübergehend zu viele Prozesse im System vorhanden sind. Eine direktere Ursache wäre sendmail, die vorzeitig abbricht, bevor alle Standardeingaben gelesen werden, zum Beispiel aufgrund von fehlerhaften E-Mail-Headern.

popen ist leider keine sehr zuverlässige Schnittstelle. Sie können besser mit fork/execve oder posix_spawn, entweder mit einer temporären Datei für die Eingabe oder E/A-Multiplexing mit poll, nur in der Lage sein, alle Fehler, die sendmail generieren könnte erfassen. Alternativ können Sie versuchen, sendmail mit -oee aufzurufen, die alle Fehler per E-Mail melden soll, aber es wird nicht helfen, wenn die Erstellung der sendmail selbst fehlschlägt.

+0

Es war sendmail, die unerwartet aufhörte, weil wir falsch formatierte E-Mail-Adressen übermittelten. Danke für das Stichwort! – Luchio

Verwandte Themen