Simon
Simon

Reputation: 81

How to cleanup defunct/zombie processes or close long running popen with Sinatra on Puma

I have the following in my ruby sinatra app to stream large tar files on-the-fly which works nicely but each request leaves behind a defunct/zombie child process. As soon as the browser pops up the save file dialogue the process becomes defunct.

I'm running this on Puma 2.12.2

I've tried a system call and using popen in a block instead but it closes the processes and returns before the tar command finishes, so the client receives an empty file.

Any ideas how I can either automatically cleanup defunct child processes or keep a handle on the io object but still return it so it starts streaming to the client?

get '/:dir_name' do
    headers['Content-Type']="application/octet-stream"
    headers["Content-Disposition"]="attachment;filename=#{params[:dir_name]}.tar"
    IO.popen("tar -C /home/my/files -cf - #{params[:dir_name]}")
end

Upvotes: 1

Views: 964

Answers (1)

Simon
Simon

Reputation: 81

The code above appears to spawn two child processes: one for the tar command that closes correctly; and another that goes defunct.

When the popen is detached in the code below the defunct process does not appear and the tar command remains correctly attached as a child of the server.

get '/:dir_name' do
    headers['Content-Type']="application/octet-stream"
    headers["Content-Disposition"]="attachment;filename=#{params[:dir_name]}.tar"
    io = IO.popen("tar -C /home/my/files -cf - #{params[:dir_name]}")
    Process.detach(io.pid)
    return io
end

Upvotes: 2

Related Questions