Skip to content

Blog

redefining malloc() is evil

Especially when it's in an external library, like say, perl. It's a recipe for heap corruption when pointers allocated by the real malloc are passed to the redefined free and vice versa. Nasty. Whats worse is when that library redefines malloc(), free(), calloc() and realloc(), but leaves strdup() alone.

Guess how long it took to track that one down on windows, where valgrind is sorely missed? Too long, that's how long.

How did we live without valgrind!?

Calling SQLBindParameter() to bind SQL_TIMESTAMP_STRUCT as SQL_C_TYPE_TIMESTAMP, avoiding a datetime overflow.

I've spent a lot of time with ODBC recently, working on interfacing our PostalEngine product with SQL Server. One of the things that caused me a LOT of trouble is binding date/time values into our stored procedure calls. One of the reasons that it was hard work was lack of documentation-by-example.

This particular part of the product is a SOAP server implemented using gSOAP, and since we need to be able handle people born before the 70's, we're using ISO8601 strings for datetime values rather than the unix time_t type. We parse the string (watching out for timezones) and store it into a SQL_TIMESTAMP_STRUCT and bind a pointer to that struct as an input parameter.

Our ODBC code tries to be smart by not being too smart; when we call out to the stored procedures in the database, we bind parameters using the best fitting native C types for the data we're sending in. For each parameter in the procedure, we execute the following code:

    SWORD sqltype, ctype, scale, nullable;
    UDWORD precis;
    struct odbc_param *param = &params[i];
    SQLDescribeParam(stmt->stmt, i+1, &sqltype, &precis, &scale, &nullable);
    SQLBindParameter(stmt->stmt, i+1, param->inout, ctype, sqltype,
         precis, scale, (SQLPOINTER)param->buf, param->size,
         &param->len_ind);

The timestamp parameters are already set up with param->buf pointing to the SQL_TIMESTAMP_STRUCT, ctype is set to SQL_C_TYPE_TIMESTAMP, and param->size is set to sizeof(SQL_TIMESTAMP_STRUCT).

When this is run, the execute fails with SQLSTATE 22008, Date time overflow. Everything looks correct in the code, and most of the values we're passing are based on the description of the parameter provided by ODBC, so what's going on? It took me several hours to figure out the answer; it's the precision field screwing things up. The driver reports a precision of 16, which is the size of the timestamp structure in bytes. However, when binding the parameter, ODBC wants the precision to reflect the number of human-readable characters; 16 is too small, so the datetime would overflow it. I found that 22 is the magic number; I now have code like this:

    SWORD sqltype, ctype, scale, nullable;
    UDWORD precis;
    struct odbc_param *param = &params[i];
    SQLDescribeParam(stmt->stmt, i+1, &sqltype, &precis, &scale, &nullable);
    if (ctype == SQL_C_TYPE_TIMESTAMP) {
        precis = 22;
    }
    SQLBindParameter(stmt->stmt, i+1, param->inout, ctype, sqltype,
         precis, scale, (SQLPOINTER)param->buf, param->size,
         &param->len_ind);

and my datetime values can be bound and passed correctly.

Interestingly, you don't have this same problem when using SQLBindCol() to bind rowset cols to a SQL_TIMESTAMP_STRUCT.

So, there we have it; I posted this here in the hope that it saves someone else a few hours of scratching around in the ass-end of google's search results.

Why no ACAP?

So, I'm sitting here swearing at my "big three" applications; Gaim, Firefox and Thunderbird, because they work great if you only ever use a single machine, but are a real pain in the ass if you move between machines.

The biggest pain is Gaim; it stores its buddy list configuration in a local file, and when it starts up, it merges the buddy lists with the server side data. If you have two or more machines, only one of them will have the most up-to-date settings. If you've done a lot of reorganization to your buddy list, and switch to one of the other machines, you'll have all your buddies re-added to the server-side buddy list in their old locations, and also have the new locations from the server-side added to the local copy on disk. You need to re-organize the buddy list again. Repeat for each additional machine that you use.

Thunderbird and firefox are in a similar boat; even using IMAP, it's "impossible" (as in, too damned painful) to keep your thunderbird message filtering rules and junk mail training data synchronized. Firefox; it would be nice to sync passwords and Sage feed lists between machines.

So, why isn't there some magical way to look after this? Surprisingly, there is actually a standard protocol for exactly this purpose; it's called ACAP:

ACAP is the Application Configuration Access Protocol, an internet protocol for accessing client program options, configurations, and preference information remotely. ACAP is a solution for the problem of client mobility on the Internet. Almost all Internet applications currently store user preferences, options, server locations, and other personal data in local disk files. These leads to the unpleasant problems of users having to recreate configuration set-ups, subscription lists, addressbooks, bookmark files, folder storage locations, and so forth every time they change physical locations.

This sounds perfect, but why don't "the big three" apps support it? It might have something to do with the lack of ACAP implementations. Where are they? Is anybody working on them? Is anybody selling them? What sounds like a great idea from 1997 still isn't here with any real presence in 2005. What went wrong?

I've had a quick look at the ACAP RFC and it seems overly complicated (it's based on IMAP--urgh!) so perhaps this has something to do with it. Maybe there just wasn't enough demand for ACAP, so it got shelved.

Whatever the reason, I wonder why we don't have even a simplified ACAP-style preferences server or service today. Am I just looking in the wrong places?

Synergy

I just set up Synergy so that I can use my WinXP laptop keyboard and mouse to slide over onto my multi-head setup at work and control those machines.

I was going to use x2x (which works under cygwin), but it seems to only see the right hand head. A bit of Googling turned up Synergy and, aside from a little bit of a learning curve, it works great.

The trick is to run the server process on the machine that has the physical keyboard and mouse, and run client processes on the machines that you want to incorporate into your virtual multi-monitor setup.

Reply to forwarded message in Thunderbird

Why won't it let you do it??

Am I the only person that gets forwarded email (as an attachment) and that needs to reply to the original sender?

It seems to me that someone went out of their way to prevent you from doing it; well, slap their wrists!

Back to the UK for a week

I'm about to depart for the UK for the Inbox Outbox conference. I'm leaving a little early so that I can fit in some family and friends time over the weekends and some other business either side of the conference itself.

Normally, I would say something about having choppy internet access, but given that I have none at home right now, whatever I'll have will be better than nothing. I hope. :)

Crappy cable day, and Geek Fantasies

Comcast has had really crappy internet connectivity tonight, which has made it frustrating to try to get any hacking done--surprising how many projects I have simmering right now that need to access the 'net.

While I'm here, I'll post this rather amusing link to geekfantasies.com; I saw it mentioned on TV the other night but the site was down (bandwidth limit exceeded!).

rtl8180 under linux 2.6

You need to use ndiswrapper and the driver from the RealTek site; using the driver provided on the CD that came with my cheapo pcmcia card led to a panic on startup.

Update: According to Russel Phillips (some guy I don't know--his words :-) Realtek have recently released a Linux 2.6 driver for this chap. I've not tested this yet, as I'm not sure where I put the pcmcia card, and the ipw2200 driver for my internal wifi works like a champ.

New toys for me

In anticipation of the imminent sale of our house back in England, we decided that some retail therapy was in order this weekend.

My top 3 toys are:

b2c_l_213t-black.jpg.t

Samsung SyncMaster 213T, a 21" flatscreen that looks really nice at 1600x1200. I have the silver version. You can rotate it into portrait mode and work at 1200x1600, which is an interesting new perspective for productivity. You'll need a chair with adjustable height control though, as the extra couple of inches of height are enough to require that you tilt your head back to read the top of the screen.

4e928caa-b20e-442e-a6d1-5dbef92442eb_large.jpg.t

Microsoft Wireless Optical Desktop, Comfort Edition, a not-so-severe take on the "Natual" keyboard idea--makes it much easier to transition between it and a laptop keyboard. If you've ever found yourself tapping the blank space between the two halves of a natural keyboard, you'll appreciate this one.

GCS632Usm.jpg.t

IOGEAR MiniView(tm) Micro USB PLUS KVM Switch an inexpensive USB KVM that allows me to use the keyboard and screen (and audio too, but I don't have that hooked up) with my machine and share it with Juliette's G4.

It all works very nicely, except that the KVM is a little too cheap to realize that the optical desktop needs only a single USB connector for both the mouse and keyboard. Depending on which port you plug into, you can either use only the keyboard (no mouse), or use the keyboard and mouse, but can't use any hotkeys to switch the KVM over to the other machine. My workaround for this was to use the latter, and plug in an older USB keyboard to the other socket and simply double-tap the scroll-lock key on that one when I need to make the switch. I have the second keyboard stowed under the desk but sitting on top of the G4--within easy tapping reach, and away from the desk top.

Why they can't just have a button on the top of the KVM itself eludes me, but at least it works and it didn't cost a fortune.

gmail saga continues

I have 32 left, which means that I've managed to shed around 70 invites over the last few weeks. If you're still interested, let me know.

Update: Argh, up to 50 again.