in reply to readline succeeds but sets $! = EBADF

Quoting from man errno on a Linux box:

Its value is significant only when the call returned an error (usually -1), and a library function that does succeed is allowed to change errno.

There's similar language in Stevens' APUE (p14, section 1.7) that you only look at errno when a failure is indicated. So it's not inconceivable that something in the C layers underneath might diddle errno preemptively and then never clear it (relying on the return code to indicate success).

Update: bleh, left out the important qualifier "when a failure is indicated" above.