From: Robert Klemme Date: 2003-09-19T17:37:19+09:00 Subject: Re: closing stderr "Mark J. Reed" schrieb im Newsbeitrag news:20030918162950.GA14933@mulan.thereeds.org... > On Fri, Sep 19, 2003 at 12:49:43AM +0900, Michael Garriss wrote: > > I would like to prevent some output that is going to stderr during a > > call to a third party lib just during that call. My first guess was: > > > > STDERR.close_write > > ThirdPartyLib::call_some_annoying_function > > STDERR.???? > > If the third-party library is a Ruby library and is well-behaved, > then you don't have to mess with STDERR; just change $stderr to > point to someplace else. > > Remember: the global variable $stderr is where Ruby actually sends > standard error output. The constant STDERR is just a saved > copy of the value $stderr got when Ruby started up. Ah, thanks for reminding me! > So something like this should do the trick: > > begin > $stderr = File.open('/dev/null', 'w') > ThirdPartyLib::call_some_annoying_function > ensure > $stderr = STDERR > end I typically prefer $stderr = File.open('/dev/null', 'w') begin ThirdPartyLib::call_some_annoying_function ensure $stderr = STDERR end because if the resource assignment (File.open) fails with an exception, no assignment takes place and thus $stderr = STDERR is superfluous. In this simple example there is no functional and not much performance difference but if the init and cleanup actions are more complex then it might indeed be crucial to follow the pattern to do the init before the block. Just as an additional note, this complete scheme might break in multithreaded applications. You migh lose messages from other threads or other strange things. That's the price of $globals... > If, on the other hand, the third-party library is not so well-behavied > and messes with STDERR directly, then you can close it. But you need to save > a copy of it first and restore it later. > > begin > errCopy = ($stderr = STDERR).dup > STDERR.close > ThirdPartyLib::call_some_annoying_function > ensure > $stderr = errCopy > STDERR = $stderr > end > > Note that you have to assign something open to $stderr before assigning > to STDERR, or else the assignment to STDERR throws an exception trying to > print the "already initialized constant" warning and the assignment > doesn't complete. There is probably a cleaner way of doing this. (see above) > Question on the subject of well-behaved libraries: if you invoke > native code from Ruby, is that run with file descriptor 2 initially > matching $stderr? Dunno. Kind regards robert