Reminder: Don’t Hard Code It

April 6th, 2010

Today’s reminder comes from the “magic number” department, where we remind you to never hard-code a magic number in your software. For example, the value for ETIMEDOUT on Linux can vary depending on your C library. glibc, for example, defines it as 110, but uClibc defines it as 145. This tends to matter when you are using a return value from, for example, libusb, at an important branching point in your software. Of course, this whole exercise is hypothetical. I would never hard code a number like that, of course not.

The upside:
The libusb source code is available for the world to see.

The downside:
The libusb documentation makes no mention of ETIMEDOUT.

7 Responses to “Reminder: Don’t Hard Code It”

  1. Byron Clark Says:

    I’m a little curious where that 145 is coming from. On two of my systems (x86-archlinux and armel-debian), ETIMEDOUT is defined in /usr/include/asm-generic/errno.h.

    Here’s the package on x86-archlinux:
    % pacman -Qo /usr/include/asm-generic/errno.h
    /usr/include/asm-generic/errno.h is owned by linux-api-headers 2.6.33.1-1

    And here’s the package on armel-debian:
    $ dpkg -S /usr/include/asm-generic/errno.h
    linux-libc-dev: /usr/include/asm-generic/errno.h
    $ apt-cache show linux-libc-dev | grep ^Source:
    Source: linux-2.6

    I don’t see ETIMEDOUT defined anywhere in uClibc.

    The only place on my system where I see ETIMEDOUT defined to 145 is in /usr/include/mysql/my_pthread.h, but that’s only when __WIN__ is defined.

    Do you have some odd kernel headers in your cross compilation environment?

  2. Dave Says:

    Byron,

    It’s possible. I’m using OpenWrt/BuildRoot with uClibc. I’ll check it out.

    –Dave

  3. Dave Says:

    Okay, Byron, check out this tiny C program:

    #include <stdio.h>
    #include <errno.h>
    
    int main()
    {
        printf("ETIMEDOUT: %d\n", ETIMEDOUT);
    }
    

    When I run it on Ubuntu and OpenSuse 11.0 (both using glibc), it prints:

    ETIMEDOUT: 110

    But when I run it on OpenWrt/uClibc, it prints:

    ETIMEDOUT: 145

    I don’t know where it’s defined, but it definitely looks different to me. What’s your take?

  4. Byron Clark Says:

    Here’s an easy way to find where the definition comes from. Just add this line before main() in your test program:

    #define ETIMEDOUT 999

    When you build, gcc should spit out a nice error like this one:

    etimedout.c:4:1: warning: “ETIMEDOUT” redefined
    In file included from /usr/include/asm/errno.h:1,
    from /usr/include/linux/errno.h:4,
    from /usr/include/bits/errno.h:25,
    from /usr/include/errno.h:36,
    from etimedout.c:2:
    /usr/include/asm-generic/errno.h:83:1: warning: this is the location of the previous definition

    Do you check for ETIMEDOUT as a return value somewhere in your code? I ask because it looks like libusb only checks for it once and uses ETIMEDOUT as a constant, so it shouldn’t matter what the value is unless it was different when your buildroot for OpenWrt was created.

  5. Dave Says:

    Okay, looks like it’s defined here on OpenWrt:

    staging_dir/toolchain-mips_r2_gcc-4.3.3+cs_uClibc-0.9.30.1/mips-openwrt-linux-uclibc/sys-include/errno.h:98

       #define ETIMEDOUT 145

    And here on Ubuntu:

    /usr/include/asm-generic/errno.h:83

       #define ETIMEDOUT 110
  6. Dave Says:

    P.S. I’m using gcc 4.4.1 on Ubuntu, not sure of the libc version.

  7. Dave Says:

    By the way, the only reason I used a hard-coded 110 in my code was because I hadn’t read the libusb code to know what it was returning. I had searched their documentation trying to figure out what values to expect, but could find no reference to ETIMEDOUT. When I ported my app to OpenWrt/uClibc, that’s when I realized that libusb was returning something different (145 it turnd out), and only then did I read their code to figure out just what symbol that was. So yes, in short, I was checking for that as a libusb return value (from usb_bulk_read() actually), and after I discovered that libusb uses ETIMEDOUT, I changed my code to also check for ETIMEDOUT rather than 110.

Leave a Reply