Ignore my previous ramblings. I've worked it out. In case it helps someone else ... The process was defunct because the parent hadn't done a wait() for it. I was able to change my status checking to the equivalent of puts (Process.waitpid(pid, Process:WNOHANG) == pid) ? "dead" : "alive" which works a treat (although, I'll have to think a bit more about error cases).