" /> TechnicaLee Speaking: December 2005 Archives

Main | January 2006 »

December 16, 2005

Ruby on Rails, ActiveSupport, and EBADF

While trying to setup Ruby on Rails in my Cygwin environment:

panicale:~/My Documents/ruby/sandbox 28>ruby script/server 
/usr/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/core_ext/kernel.rb:53:in ``': Bad file descriptor - lighttpd -version (Errno::EBADF)
        from /usr/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/core_ext/kernel.rb:53:in ``'
        from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/server.rb:15
        from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/server.rb:15:in `silence_stderr'
        from /usr/lib/ruby/gems/1.8/gems/rails-1.0.0/lib/commands/server.rb:15
        from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:21:in `require__'
        from /usr/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:21:in `require'
        from /usr/lib/ruby/gems/1.8/gems/activesupport-1.2.5/lib/active_support/dependencies.rb:214:in `require'
        from script/server:3

Web searches proved fruitless, and so I dug into the cause of the error by hand. Line 53 in ActiveSupport's kernel extension is an override of the backtick command to make a nonexistent command behave similarly in both Unix and Windows environments. But my problem is not a nonexistent command, so this error is likely not a function of this particular override of backticks. So we add the line STDOUT.puts "** RUNNING COMMAND: #{command} before the actual execution of the command. Let's see during what command we're faulting. This yielded: ** RUNNING COMMAND: lighttpd -version. To the command line we go!

But wait, what's this?

panicale:~ 34>which lighttpd
lighttpd: Command not found.

Checking into line 15 of server.rb we see that Rails is attempting to start lighttpd, and in the absence thereof (actually, if something is written to standard error while attempting to ascertain the version of lighttpd), to go with the built-in WEBrick web server. I don't have lighttpd, and yet it seems that someone (Windows? Cygwin?) is throwing a bad file descriptor error (EBADF) instead of a nonexistent command error (ENOENT) when Ruby tries to execute lighttpd -version. Why? I have no idea.

The fix is easy; simply extend ActiveSupport's transformation from exception to STDERR output to apply to EBADF in addition to ENOENT:

<   rescue Errno::ENOENT => e
>   rescue Errno::ENOENT, Errno::EBADF => e