Error handling

Discussion in 'C Programming' started by dgiagio@gmail.com, Jan 11, 2006.

  1. Guest

    Hi,

    I'm creating a SMTP application and I would like to hear opinions about
    error handling. Currently there are two functions that communicate with
    the remote peer:

    ssize_t smtp_puts(smtp_stream_t *stream, const char *fmt, ...);
    ssize_t smtp_gets(smtp_stream_t *stream, char *buf, size_t len);

    Both of them return the number of written bytes to the stream, or -1 if
    an error ocurred. The error is set on errno, since they use write() and
    read().

    My approach is like the following:

    if (smtp_puts(s, "HELO hostname") == -1) {
    syslog(LOG_ERR, "smtp_puts: sending HELO: %m");
    goto cleanup;
    }

    if (smtp_gets(s, buf, sizeof(buf) == -1) {
    syslog(LOG_ERR," smtp_gets: receiving HELO: %m");
    goto cleanup;
    }

    /* Process the HELO response */
    if (smtp_check_helo(buf) == -1) {
    syslog(LOG_ERR, "smtp_check_helo: bad HELO");
    goto cleanup;
    }

    if (smtp_puts(s, "MAIL FROM:<postmaster>") == -1) {
    syslog(LOG_ERR, "smtp_puts: sending MAIL FROM: %m");
    goto cleanup;
    }

    if (smtp_gets(s, buf, sizeof(buf) == -1) {
    syslog(LOG_ERR," smtp_gets: receiving MAIL FROM: %m");
    goto cleanup;
    }

    /* Process the MAIL FROM response */
    if (smtp_check_mailfrom(buf) == -1) {
    syslog(LOG_ERR, "smtp_check_mailfrom: bad MAIL FROM");
    goto cleanup;
    }

    /* And this keep going... RCPT TO, DATA, RSET, QUIT, etc... */

    cleanup:
    smtp_stream_close(s);
    return 0;


    I've been reading Postfix sources and it seems they use setjmp/longjmp
    for exceptions on . I don't think that's a good approach, so I'm asking
    it here. Qmail's approach is to _exit() on most errors, which is ugly.

    What would be a 'good' error handling mechanism for this kind of
    situation?
    Thanks
     
    , Jan 11, 2006
    #1
    1. Advertising

  2. Flash Gordon Guest

    wrote:
    > Hi,
    >
    > I'm creating a SMTP application and I would like to hear opinions about
    > error handling. Currently there are two functions that communicate with
    > the remote peer:
    >
    > ssize_t smtp_puts(smtp_stream_t *stream, const char *fmt, ...);
    > ssize_t smtp_gets(smtp_stream_t *stream, char *buf, size_t len);
    >
    > Both of them return the number of written bytes to the stream, or -1 if
    > an error ocurred. The error is set on errno, since they use write() and
    > read().


    For your information (and this is not a complaint) if you have problems
    with read/write then please ask them else where, maybe
    comp.unix.programmer, since we only deal with standard C not Posix or
    Windows specifics.

    Your question is not to do with read/write and you provide enough
    information about the function your don't provide, so it is entirely
    topical.

    > My approach is like the following:
    >
    > if (smtp_puts(s, "HELO hostname") == -1) {
    > syslog(LOG_ERR, "smtp_puts: sending HELO: %m");
    > goto cleanup;
    > }
    >
    > if (smtp_gets(s, buf, sizeof(buf) == -1) {
    > syslog(LOG_ERR," smtp_gets: receiving HELO: %m");
    > goto cleanup;
    > }
    >
    > /* Process the HELO response */
    > if (smtp_check_helo(buf) == -1) {
    > syslog(LOG_ERR, "smtp_check_helo: bad HELO");
    > goto cleanup;
    > }
    >
    > if (smtp_puts(s, "MAIL FROM:<postmaster>") == -1) {
    > syslog(LOG_ERR, "smtp_puts: sending MAIL FROM: %m");
    > goto cleanup;
    > }
    >
    > if (smtp_gets(s, buf, sizeof(buf) == -1) {
    > syslog(LOG_ERR," smtp_gets: receiving MAIL FROM: %m");
    > goto cleanup;
    > }
    >
    > /* Process the MAIL FROM response */
    > if (smtp_check_mailfrom(buf) == -1) {
    > syslog(LOG_ERR, "smtp_check_mailfrom: bad MAIL FROM");
    > goto cleanup;
    > }
    >
    > /* And this keep going... RCPT TO, DATA, RSET, QUIT, etc... */
    >
    > cleanup:
    > smtp_stream_close(s);
    > return 0;


    <OT>
    My reading of the RFC for SMTP suggested that you should send an "RSET"
    if you are part way through sending the email and decide to give up, and
    that you should send a "QUIT" to log off the mail server. Obviously, the
    mail server has to handle it properly if you just drop the connection,
    so it's no big deal.

    Don't bother correcting me if I'm wrong because it's off topic here and
    I would not have mentioned it at all if I was not responding to your
    main point.
    </OT>

    > I've been reading Postfix sources and it seems they use setjmp/longjmp
    > for exceptions on . I don't think that's a good approach, so I'm asking
    > it here. Qmail's approach is to _exit() on most errors, which is ugly.


    As far as I am aware C provides exit(), abort() and, with the new C99
    standard, _Exit() but does not provide an _exit() function.

    > What would be a 'good' error handling mechanism for this kind of
    > situation?


    Of the three solutions you have presented I prefer yours. However, I'll
    present another solution, one I used when writing a simple SMTP client
    some years ago was something like:

    static int dirtysendmail(parameters...)
    {
    /* do stuff */
    if (whatever)
    return MY_ERR1;
    /* do more stuff */
    if (whateverelse)
    return MY_ERR2;
    /* and so on */
    return 0; /* success */
    }

    int sendmail(parameters...)
    {
    int ret=dirtysendmail(parameters...);
    switch (ret) {
    case default: /* try to send a RSET */
    case 0: /* try to send a QUIT */
    case ERR_MEANING_NOT_EVEN_GOT_HELO_OUT: /* try to close socket */
    }
    return ret;
    }

    Note the lack of breaks in the switch so that it falls through and the
    amount of tidying up done depends on how far it got.

    In my case exiting the application was not appropriate since the smtp
    client is embedded within a larger application, and people don't want to
    be kicked out just because it can't send email notifications! With qmail
    I would guess you are looking at a program that sends (or fails to send)
    one email then exits, so exiting as soon as it has failed is not
    necessarily unreasonable.
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Jan 11, 2006
    #2
    1. Advertising

  3. Flash Gordon <> writes:
    [...]
    > int sendmail(parameters...)
    > {
    > int ret=dirtysendmail(parameters...);
    > switch (ret) {
    > case default: /* try to send a RSET */
    > case 0: /* try to send a QUIT */
    > case ERR_MEANING_NOT_EVEN_GOT_HELO_OUT: /* try to close socket */
    > }
    > return ret;
    > }
    >
    > Note the lack of breaks in the switch so that it falls through and the
    > amount of tidying up done depends on how far it got.


    And since you're showing us pseudo-code, the "case default:" is an
    acceptable way of writing the syntactically correct "default:".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.
     
    Keith Thompson, Jan 11, 2006
    #3
  4. Flash Gordon Guest

    Keith Thompson wrote:
    > Flash Gordon <> writes:
    > [...]
    >> int sendmail(parameters...)
    >> {
    >> int ret=dirtysendmail(parameters...);
    >> switch (ret) {
    >> case default: /* try to send a RSET */


    <snip>

    > And since you're showing us pseudo-code, the "case default:" is an
    > acceptable way of writing the syntactically correct "default:".


    Yes, that is!

    <fx:wanders off muttering/>
    --
    Flash Gordon
    Living in interesting times.
    Although my email address says spam, it is real and I read it.
     
    Flash Gordon, Jan 11, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Kenneth Keeley

    Error Handling

    Kenneth Keeley, Jul 1, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    382
    Kenneth Keeley
    Jul 1, 2003
  2. VSK
    Replies:
    1
    Views:
    792
    Alvin Bruney
    Jul 29, 2003
  3. Mark Tarver
    Replies:
    22
    Views:
    1,316
    J Kenneth King
    Apr 26, 2009
  4. Peter
    Replies:
    34
    Views:
    1,943
    James Kanze
    Oct 17, 2009
  5. Iñaki Baz Castillo
    Replies:
    1
    Views:
    191
    Iñaki Baz Castillo
    Apr 15, 2008
Loading...

Share This Page