Reputation: 81
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
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