April 19th, 2006

EBADF in SBCL

I have been working with SBCL sockets for the saywhat website. Every now and then I would get errors like this:

error in Unix lseek() on #<SB-SYS:FD-STREAM for "file /opt/wf/src/skippy/slkscr.ttf" {C9A41B9}>:
   Bad file descriptor

couldn't write to #<SB-SYS:FD-STREAM for "file /opt/wf/site/sw/bubbles/0/h/qJy3EKX7vD.png" {D0DE7F9}>:
   Bad file descriptor

I did not even know where to start debugging this. Fortunately, Robert Macomber pointed me in the right direction: finalizers.

My socket interation went something like this:

  1. Create socket with (make-instance 'sb-bsd-sockets:inet-socket ...)
  2. Work with socket fd with epoll(), read(), write(), and sendto()
  3. Close the socket fd with sb-posix:close
  4. Some subsequent operation opens and works with the fd number previously assigned to the socket
  5. The socket finalizer runs, closing the fd
  6. The next operation on the fd returns EBADF

The standard function sb-bsd-sockets:socket-close will both close the socket fd and cancel the finalization, preventing the future closure of the wrong fd. Since switching from sb-posix:close to sb-bsd-sockets:socket-close, the problem has gone away. Thanks Robert!