The Boston Diaries

The ongoing saga of a programmer who doesn't live in Boston, nor does he even like Boston, but yet named his weblog/journal “The Boston Diaries.”

Go figure.

Wednesday, Debtember 02, 2009

I told you handing errors was error prone

From
Mark Grosberg <XXXXXXXXXXXXXXXXX>
To
sean@conman.org
Subject
Blog post.
Date
Wed, 2 Dec 2009 15:59:55 -0500 (EST)

I find it even more amusing that you didn't get the error handling right in the create_socket() on your current blog post.

Notice that you leak the socket and/or memory in the error cases. I guess it really is hard to handle errors. ;-)

Sorry, I just had to take this cheap shot!

-MYG

Heh.

Yup, I blew it again for demonstration purposes.

The code I posted yesterday was actually pulled from a current project where the create_socket() is only called during initialization and if it fails, the program exits. Since I'm on a Unix system, the “lost” resources like memory and sockets are automatically reclaimed. Not all operating systems are nice like this.

There are a few ways to fix this. One, is to use a langauge that handles such details automatically with garbage collection, but I'm using C so that's not an option. The second one is to add cleanup code at each point we exit, but using that we end up with code that looks like:

  /* ... */

  if fcntl(listen->sock,F_GETFL,0) == -1)
  {
    perror("fcntl(GETFL)");
    close(listen->socket); 
    free(listen);
    return -1;
  }
   
  if (fcntl(listen->sock,F_SETFL,rc | O_NONBLOCK) == -1)
  {
    perror("fcntl(SETFL)");
    close(listen->socket); 
    free(listen);
    return -1;   
  }
   
  if (bind(listen->sock,paddr,saddr) == -1)
  {
    perror("bind()");
    close(listen->socket);
    free(listen);
    return -1;   
  }

  /* ... */

Lots of duplicated code and the more complex the routine, the more complex the cleanup and potential to leak memory (or other resources like files and network connections). The other option looks like:

  /* ... */

  if fcntl(listen->sock,F_GETFL,0) == -1)
  {
    perror("fcntl(GETFL)");
    goto create_socket_cleanup;
  }
  
  if (fcntl(listen->sock,F_SETFL,rc | O_NONBLOCK) == -1)
  {
    perror("fcntl(SETFL)");
    goto create_socket_cleanup;
  }

  if (bind(listen->sock,paddr,saddr) == -1)
  {
    perror("bind()");
    goto create_socket_cleanup;
  }

  /* rest of code */

  return listen->sock; /* everything is okay */

create_socket_cleanup:
  close(listen->sock);
create_socket_cleanup_mem:
  free(listen);
  return -1;
}

This uses the dreaded goto construct, but is one of the few places that it's deemed “okay” to use goto, for cleaning up errors. No code duplication, but you need to make sure you cleanup (or unwind, or whatever) in reverse order.

So yeah, error handling … maddening.

I still wish there was a better way …

Obligatory Picture

[The future's so bright, I gotta wear shades]

Obligatory Contact Info

Obligatory Feeds

Obligatory Links

Obligatory Miscellaneous

You have my permission to link freely to any entry here. Go ahead, I won't bite. I promise.

The dates are the permanent links to that day's entries (or entry, if there is only one entry). The titles are the permanent links to that entry only. The format for the links are simple: Start with the base link for this site: https://boston.conman.org/, then add the date you are interested in, say 2000/08/01, so that would make the final URL:

https://boston.conman.org/2000/08/01

You can also specify the entire month by leaving off the day portion. You can even select an arbitrary portion of time.

You may also note subtle shading of the links and that's intentional: the “closer” the link is (relative to the page) the “brighter” it appears. It's an experiment in using color shading to denote the distance a link is from here. If you don't notice it, don't worry; it's not all that important.

It is assumed that every brand name, slogan, corporate name, symbol, design element, et cetera mentioned in these pages is a protected and/or trademarked entity, the sole property of its owner(s), and acknowledgement of this status is implied.

Copyright © 1999-2024 by Sean Conner. All Rights Reserved.