Nice analysis Ian and John, thanks for digging in to this. I agree with what you've determined, though I think there was a missing 'uptodate' line from the code too. I'm attaching a diff that matches yours but has this extra line. Can you please confirm that this still gives you the behaviour you're expecting? Thanks.
Index: crypto/engine/eng_table.c =================================================================== RCS file: /v/openssl/cvs/openssl/crypto/engine/eng_table.c,v retrieving revision 1.6.2.1 diff -u -r1.6.2.1 eng_table.c --- crypto/engine/eng_table.c 6 Sep 2007 12:43:49 -0000 1.6.2.1 +++ crypto/engine/eng_table.c 27 Apr 2008 19:27:52 -0000 @@ -135,7 +135,7 @@ { fnd = OPENSSL_malloc(sizeof(ENGINE_PILE)); if(!fnd) goto end; - fnd->uptodate = 0; + fnd->uptodate = 1; fnd->nid = *nids; fnd->sk = sk_ENGINE_new_null(); if(!fnd->sk) @@ -152,7 +152,7 @@ if(!sk_ENGINE_push(fnd->sk, e)) goto end; /* "touch" this ENGINE_PILE */ - fnd->uptodate = 1; + fnd->uptodate = 0; if(setdefault) { if(!engine_unlocked_init(e)) @@ -164,6 +164,7 @@ if(fnd->funct) engine_unlocked_finish(fnd->funct, 0); fnd->funct = e; + fnd->uptodate = 1; } nids++; } @@ -179,8 +180,7 @@ while((n = sk_ENGINE_find(pile->sk, e)) >= 0) { (void)sk_ENGINE_delete(pile->sk, n); - /* "touch" this ENGINE_CIPHER */ - pile->uptodate = 1; + pile->uptodate = 0; } if(pile->funct == e) {