Writing to STDOUT after closing controlling terminal

M

Matt Bleh

Hi,
I don't know if this is a dumb question or not (I hope it isn't), but it
seems to me there's something wrong here. I've been using Ruby for a
long time now, and I never noticed this (maybe it wasn't working like
this in the past), and it just seems odd.
If I write the following code:

sleep(5)
begin
puts 'hi!'
rescue
File.open('output', 'w') {|io| io.puts $!.message }
end

And execute it in Ruby 1.9.1p243 in a graphical terminal (e.g.: konsole)
as a foreground process I obviously get this:

$ ./test.rb
hi!

And there's no "output" file created sine no exception was raised.

Now, If I do:
$ ./test.rb &
[1] 28137
and immediately close konsole, 5 seconds later I get:
$ cat output
Input/output error - <STDOUT>

Is this ok? I seems to me that one shouldn't have to care if the
controlling terminal is closed when doing "puts" to avoid this exception
from ending my ruby process.

As a sidenote, with Ruby 1.8.7p174 the process doesn't get any
exception. If now I write (to check for normal process completion):

sleep(5)
begin
puts 'hi!'
File.open('output2', 'w') {|io| io.puts 'ok' }
rescue
File.open('output', 'w') {|io| io.puts $!.message }
end
with

and execute it as before, I get the "output2" file with the "ok" string
in it.

Is this a bug? a feature?

Thank you,
Matt
 
M

Mario Camou

[Note: parts of this message were removed to make it a legal post.]

As far as killing the controlling terminal is concerned, AFAIK it's standard
Unix practice. If you want the process to stay alive even if you kill the
terminal, you either redirect its stdin/stdout or use nohup.
-Mario.
 
M

Matt Bleh

Mario said:
As far as killing the controlling terminal is concerned, AFAIK it's
standard
Unix practice. If you want the process to stay alive even if you kill
the
terminal, you either redirect its stdin/stdout or use nohup.
-Mario.

I know it's not enough justification, but doing an "echo 1" from a
backgrounded bash script process doesn't kill the script. I understand
that you should redirect STDOUT, but in Ruby should programmers really
need to concern about this?
Or maybe this would translate to the users of that Ruby program to be
forced to redirect STDOUT and STDERR to /dev/null or something (which
also seems a bit weird to me).
 
D

David Masover

I know it's not enough justification, but doing an "echo 1" from a
backgrounded bash script process doesn't kill the script.

That's because your script is badly written. Try this script:

#!/bin/sh
sleep 5
echo hi || echo $! > output

This has exactly the same behavior as your Ruby script, except that you're
only capturing the return value of that first echo command.

In other words: In a shell script (bash or otherwise), the 'echo' command does
indeed get killed. It's just that by default, shell scripts ignore the return
values, which means errors are silently eaten. Ruby, on the other hand, raises
an exception when something goes wrong.

I don't like silent errors, so I usually write shell scripts that look more
like this:

#!/bin/sh
first line &&
second line &&
third line &&
fourth line

That way, the script dies at the first error, unless I explicitly handle it.
I understand
that you should redirect STDOUT, but in Ruby should programmers really
need to concern about this?

If you don't want to be concerned about this, abstract it away with some sort
of logging class. I'm glad Ruby has the same behavior as any other language,
when it comes to basic Unix semantics like this -- and I'm glad my output
doesn't just silently get eaten when I close the terminal.
 
S

Seebs

I don't like silent errors, so I usually write shell scripts that look more
like this:

You might use "set -e". I don't, but I check exactly those errors I care
about. (I don't necessarily care about loss of output.)

-s
 
M

Matt Bleh

David said:
That's because your script is badly written. Try this script:

#!/bin/sh
sleep 5
echo hi || echo $! > output

This has exactly the same behavior as your Ruby script, except that
you're
only capturing the return value of that first echo command.

In other words: In a shell script (bash or otherwise), the 'echo'
command does
indeed get killed. It's just that by default, shell scripts ignore the
return
values, which means errors are silently eaten. Ruby, on the other hand,
raises
an exception when something goes wrong.


Ok, I didn't realized that about the bash script.
So, this means that this difference between ruby 1.8 and ruby 1.9 is a
feature?
I guess that I should then use nohup if I don't want to think about this
issue when writing other Ruby programs.
 
D

David Masover

So, this means that this difference between ruby 1.8 and ruby 1.9 is a
feature?

In my opinion.
I guess that I should then use nohup if I don't want to think about this
issue when writing other Ruby programs.

Depends what you're using the output for. I would use some sort of logger, if
you can't count on stdout being redirected.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,577
Members
45,054
Latest member
LucyCarper

Latest Threads

Top