2012-10-18 7 views
12

Nella mia applicazione GUI multithread ho il seguente codice di gestione del segnale. Voglio migliorare il codice in modo che sarà corretto e filettatura sicura ma ci sono alcune cose che non capiscono fino in fondo nella gestione del segnale:Funzione di gestione del segnale in ambiente multithreading

  • è il segnale gestite a livello di processo o thread (posso avere filo - gestori di segnali specifici)?
  • in quale contesto di thread è eseguita la funzione signal_handler?
  • è possibile inviare molti segnali SIGTERM in breve tempo?
  • ha senso utilizzare un mutex per impedire l'esecuzione parallela di signal_handler?

void signal_handler(int sig) 
{ 
     switch (sig) 
     { 
     case SIGTERM: 
      ::wxLogMessage(wxT("SIGTERM signal received ...")); 
      break; 
     case SIGINT: 
      ::wxLogMessage(wxT("SIGINT signal received ...")); 
      break; 
     case SIGUSR1: 
      ::wxLogMessage(wxT("SIGUSR1 signal received ...")); 
      break; 
     default: 
      ::wxLogMessage(wxT("Unknown signal received ...")); 
     } 

     // send wxCloseEvent to main application window 
     ::wxGetApp().GetTopWindow()->Close(true); 
} 

mi iscrivo gestori di segnale nella mia funzione init:

// register signal handlers 
signal(SIGTERM, signal_handler); 
signal(SIGINT, signal_handler); 
signal(SIGUSR1, signal_handler); 

risposta

10

Fate molta attenzione: come pagina signal(7) sta dicendo, solo pochissime funzioni (il "segnale asincrono -safe "" può essere (direttamente o indirettamente) chiamato all'interno dei gestori di segnale. Probabilmente le funzioni relative al mutex non dovrebbero essere chiamate nei gestori di segnale. Vedere anche pthreads(7)

È possibile impostare una variabile volatile sigatomic_t nel gestore di segnale e verificare il valore di tale indicatore di volta in volta. Se si dispone di atomici C++ 11 (o C11), ad es. C++ 11 std::atomic o C11 <stdatomic.h>, è possibile che anche la variabile volatile sia atomica in questo senso. Quindi utilizzare le strutture di carico atomico per testarlo.

La documentazione Qt suggerisce il following trick: creare un pipe(2) per sé all'avvio, quindi avere il vostro gestore di segnale write(2) (la write syscall è specificato come async-signal-safe) un singolo (o più) byte [s] per una pipe per il tuo stesso processo, e avere il tuo ciclo di eventi GUI poll(2) l'estremità letta di quella pipe.

A specifico per Linux modo per gestire segnali con Qt potrebbe essere quella di utilizzare signalfd(2) probabilmente con QSocketNotifier (nonostante il nome, funziona su descrittori di file pollable, non solo socket). Con altri toolkit della GUI, è possibile anche aggiungere un descrittore di file (quello da signalfd o pipe) per il polling.

+2

L'utilizzo di note di std :: atomic nei gestori di segnale non garantisce implementazioni senza lock. Si prega di consultare: http://www.informit.com/articles/article.aspx?p=2204014 – Corvusoft

4

Questa risposta si riferisce ai thread POSIX (pthreads).

riferimento 1:

segnali possono essere trattati a livello filo, sì. Se più di un thread di un processo gestisce un segnale e il segnale viene inviato al processo, ma a un thread specifico non viene determinato quale gestore del thread gestirà il segnale. (Vedi man pthread_kill() per i dettagli)

riferimento 2:

il gestore di segnale viene excuted nel contesto del filo che impostarlo. Questo include il thread principale.

riferimento 3:

Se più di un segnale dello stesso tipo viene inviato allo stesso processo potrebbero essere condensati in in un solo segnale prima di lasciare la coda segnale. Devo ammettere che questo potrebbe essere diverso dal livello del filo, non lo so per certo.

riferimento 4:

Se le risorse condivise sono coinvolte nel gioco: sì, almeno per le parti di codice dei gestori accedere a tali risorse contemporaneamente. Inoltre, ciò dipende anche dalla logica che si tenta di implementare.

17
  • I gestori di segnale sono stati per processo, ovvero tutti i thread in un processo condividono lo stesso insieme di funzioni del gestore di segnale installato.
  • Le maschere di segnale sono per stato. I segnali possono essere bloccati o sbloccati in base al thread.
  • I segnali possono essere indirizzati al processo o ai thread. Se un segnale è diretto dal processo, viene scelto un thread arbitrario che al momento non ha il tipo di segnale bloccato per gestirlo.

Un modo semplice per gestire i segnali in un'applicazione multi-thread consiste nel creare un thread come thread dedicato di gestione dei segnali. Tutti i segnali di interesse sono bloccati in ogni thread; non vengono stabiliti gestori di segnale; e il thread di gestione del segnale chiama sigwaitinfo() in un ciclo, agendo sui segnali mentre vengono ricevuti.

Questo significa che non c'è bisogno di preoccuparsi se le funzioni che si desidera chiamare sono async-signal-safe o no, perché i segnali non sono gestiti in gestori di segnale - sono gestite in modo sincrono dal vostro thread dedicato alla gestione dei segnali, che può chiamare qualsiasi funzione che gli piace (ad esempio, può utilizzare le normali funzioni di sincronizzazione pthread per risvegliare un altro thread).