Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby kill virtual shell opened with PTY.spawn

In a ruby script, I start more virtual shells, each managed by a shell manager object, like so:

@shell = PTY.spawn 'env PS1="\w>" TERM=dumb COLUMNS=63 LINES=21 sh -i'

At some later point in time, I would like to destroy this instance and also kill the associated shell process. Sadly, I can't get anything to work properly. Here's what I tried, in order of probability to work:

  • Nothing, that is, expecting the shell proc gets closed when the managing object gets destroyed.
  • Killing all processes running on the shell (this works) with the kill command, and then killing the shell itself with system("kill #{@shell[2]"). This has no effect.
  • Using -9 in the above. This leaves the shell process defunct.

All the shells get closed when the ruby program exits, but I want to kill them while keeping the program running. Anyone encounter something like this before?

like image 464
mirceapricop Avatar asked Jun 06 '26 21:06

mirceapricop


1 Answers

The problem is zombies. Yes, really.

All Unix-style kernel's leave the process around until someone waits for it. (That's in order to keep track of the PID, the exit status, and a bit of other stuff.) They are called zombies and have a Z state in the ps(1) listing. You can't kill them, because they are already dead. They go away when you wait for them.

So here is how to clean up your @shell object:

@shell[0].close
@shell[1].close
begin
  Process.wait @shell[2]
rescue PTY::ChildExited
end

You may not need the rescue block depending on whether you have higher level layers catching exceptions too broadly. (Sigh, like my irb.)

By the way, the reason your process finally vanished when the Ruby program exited is because then the zombie also became an orphan (no parent process) and either the shell or init(8) will eventually wait for all orphans.

like image 94
DigitalRoss Avatar answered Jun 08 '26 14:06

DigitalRoss



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!