Background Job e Kill

Ciao,
uso la gem BJ (Background Job,
http://codeforpeople.rubyforge.org/svn/bj/trunk/README) per gestire job
in background (ne manda uno alla volta) e ho necessità di interrompere
il processo in esecuzione.
Come posso fare?
Ora ho pensato di killare con il comando kill il processo utilizzando i
backticks:
kill -9 #{bj.pid}

E’ una buona soluzione?
Se kill e’ una buona soluzione, quale è il segnale piu’ appropriato (qui
il 9)? Si tenga presente che sarebbe opportuno che i file aperti dal
processo in esecuzione vengano correttamente chiusi.

Grazie per l’aiuto.

Ciao
iwan

Il 26 aprile 2010 23.45, Iwan B. [email protected] ha scritto:

Ciao,
uso la gem BJ (Background Job,
http://codeforpeople.rubyforge.org/svn/bj/trunk/README) per gestire job
in background (ne manda uno alla volta) e ho necessità di interrompere
il processo in esecuzione.
Come posso fare?

Ciao, do per scontato che tu stia parlando di un sistema operativo
POSIX (cioè non di Windows).
C’è il modulo Process, con il suo bravo metodo kill:

http://ruby-doc.org/core/classes/Process.html#M003152

quale è il segnale piu’ appropriato (qui il 9)? Si tenga presente
che sarebbe opportuno che i file aperti dal processo in esecuzione
vengano correttamente chiusi.

Beh, allora certamente non KILL (9), ma TERM, che è quello di default,
cioè quello che viene inviato digitando kill .

pietro

Per controllare che un processo sia attivo e nel caso riattivarlo (a
volte mi muoiono e non tornano su…) uso questa before_filter nel
controller che mi elimina il pid e rilancia l’app:

def init_cron_active
if File.file?("#{RAILS_ROOT}/lib/cal_ticker.rb.pid")
pid = “”
begin
file = File.new("#{RAILS_ROOT}/lib/cal_ticker.rb.pid", “r”)
while (line = file.gets)
pid = line.to_i
if Process.nil? or !(Process.getpgid(pid).to_i > 0)
File.unlink("#{RAILS_ROOT}/lib/cal_ticker.rb.pid")
start_ticker
end
end
file.close
rescue Exception => e
begin
File.unlink("#{RAILS_ROOT}/lib/cal_ticker.rb.pid")
Process.waitpid(pid, Process::WNOHANG)
start_ticker
rescue Exception => e
end
end
end
end

2010/4/27 Pietro G. [email protected]:

Beh, allora certamente non KILL (9), ma TERM, che è quello di default,
cioè quello che viene inviato digitando kill .

aggiungo: usare TERM o KILL non cambia molto se non gestisce nel tuo
codice il segnale, c’è #trap per questo:

trap “INT” {
cleanup();
}

la differenza è solo che KILL non puoi trapparlo, ma se non metti un
handler per il segnale non ti serve a molto usare uno o l’altro :slight_smile:

Prima di fare questo però cerca di pensare se puoi strutturare
l’applicazione in modo che sia crash-only, cioè che sia giusto
ammazzarla con SIGKILL o in qualunque altro modo.
Oltre a non dover gestire esplicitamente i segnali (con complicazioni
varie, variabili pseudo-globali etc) ti troverai con un processo che è
più resistente ad errori interni (eccezioni etc) ed esterni
(OOMKiller, fine spazio su disco, kill accidentale etc). E
probabilmente con meno codice :wink:

Ecco alla fine come ho risolto.
Una ulteriore esigenza che avevo, ma non avevo chiarito, è che venissero
uccisi tutti i processi discendenti dal primo processo, altrimenti
succede che il processo con process id (pid) viene terminato ma
l’elaborazione prosegue perché nel frattempo il mio processo ne aveva
generati altri (cosa normale se si usa BJ):

def kill_me_and_my_descendant(pid)
a = COMMAND_MODE=unix2003; ps -ef | awk '$3 == '#{pid}' { print $2 }'
a.chomp.split("\n").each do |child_pid|
kill_me_and_my_descendant(child_pid)
end
puts “>>>>>>>>>> Now killing #{pid}”
Process.kill(“KILL”, pid) # when a process is killed, his children
PPID are set to 1
# kill -9 #{pid}
end

Questa soluzione temo che non funzioni sotto Windows, io l’ho testata su
Mac OS X.
Il settaggio di COMMAND_MODE è necessario perché altrimenti l’opzione -f
di ps non viene accettata.
Il metodo è ricorsivo e fa scorrere tutti i processi figli del processo
originale e li uccide.
Da precisare infine che non ho esigenze particolari sulla chiusura
“pulita” di processi: in sintesi quello che ho è un processo java che
legge un file di testo e genera un output su un altro file di testo.

Saluti e grazie ancora
i.