2015-08-17 7 views
5

Sto tentando di eseguire una pulizia pre-spegnimento quando un SIGINT viene inviato alla mia applicazione Java, utilizzando le classi sun.misc.Signal e sun.misc.SignalHandler.Devo attivare il gestore di segnali predefinito quando definisco il mio gestore?

Appare quando registro il gestore il comportamento predefinito non si verifica più. Ma c'è un campo SignalHandler.SIG_DFL contenente "Il gestore di segnale predefinito". Prima di tutto, il comportamento del gestore predefinito è documentato ovunque? In secondo luogo, dovrei preferire il seguente schema quando implementi i miei stessi gestori?

SignalHandler handler = new SignalHandler() { 
    public void handle(Signal sig) { 
     ... // handle SIGINT 
     SignalHandler.SIG_DFL.handle(sig); 
    } 
}; 

Edit: sono consapevole il pacchetto sun.misc non è portabile, e che i ganci di arresto sono il modo più robusto per affrontare chiusura dell'applicazione. Basti dire che sono consapevole di queste funzionalità e ho bisogno di gestire i segnali direttamente. Per quanto ne so, il sun.misc.Signal è il modo corretto per farlo.

+0

Non sono sicuro di come Java gestisca in particolare i segnali, ma credo che sia coerente con l'ambiente di programmazione UNIX; in tal caso puoi vedere il comportamento di default per ciascun segnale in 'man signal' (in Linux, questo è nella Sezione 7, Mac OS sembra averlo nella Sezione 3). Probabilmente non vorrai invocare il gestore predefinito per 'SIGINT' a meno che tu non voglia terminare (l'azione predefinita per' SIGINT'). –

+0

Nel mio test, sembra che il gestore predefinito uccida (non interrompe) il thread Java 'principale', lasciando in esecuzione altri thread non daemon. Ma sono riluttante a fare affidamento sulle mie probabili osservazioni incomplete e/o imperfette. – dimo414

risposta

0

illustrata in una related question, si dovrebbe non chiamata SignalHandler.SIG_DFL nel vostro SignalHandler, come avrete causare un SEGV. In effetti, la JVM non utilizza SIG_DFL (per INT, TERM e HUP).

Under the covers tutto ciò che fa Java quando riceve uno di questi segnali è la chiamata System.exit(). Quindi, se vuoi replicare il comportamento predefinito, chiama semplicemente il numero System.exit(). Ovviamente se non si desidera uscire in risposta al segnale, non è necessario chiamare il gestore di segnale vecchio/predefinito.

Avviso: comportamento non documentato. È improbabile, ma del tutto possibile, che le versioni future di Java possano cambiare questo comportamento.

-1

Rispondere alla domanda: no non è necessario (o desidera) chiamare il gestore predefinito. Ma l'uso di questa classe non è portatile. È necessario installare il gancio di arresto:

Runtime.getRuntime().addShutdownHook(new Thread() { 
    public void run() { 
     //your graceful shutdown procedure here 
    } 
}); 
+0

Capisco il problema della portabilità, ma come usare i ganci di arresto non è una mia domanda. – dimo414