2010-06-02 5 views
7

Quelqu'un peut-il publier un exemple de code sur la façon dont je peux relire un fichier de configuration et redémarrer mon démon après que le démon ait reçu un signal SIGHUP. Le démon est un programme d'espace utilisateur écrit en C sous Linux et n'est pas lancé par inetd.Comment redémarrer le programme C daemon sous Linux après avoir reçu le signal SIGHUP

+6

Habituellement, les gens ne vous attendez pas démons à redémarrer lors de la réception de SIGHUP, mais qu'ils font un rechargement gracieux, à savoirchargement du nouveau fichier de configuration mais ne pas tomber cliens connectés et de mauvaises choses similaires. – ThiefMaster

Répondre

5

Selon la façon dont proprement votre programme est écrit, il y a (au moins) trois façons de le faire:

  1. Sur réception du signal, de retour au début du programme, avant la phase d'initialisation (éventuellement - mais pas nécessairement - via une paire setjmp()/longjmp() ou sigsetjmp()/siglongjmp(), réinitialisant et relisant ainsi le fichier de configuration.

  2. À la réception du signal, demandez au gestionnaire de signaux d'exécuter à nouveau le programme d'origine. Cela a le mérite de perdre tout l'état et de réinitialiser toutes les variables globales et statiques à leur état d'origine. Il a le démérite de perdre tout état antérieur.

  3. La troisième option est moins brutale, peut-être; il devrait noter que le signal a été reçu et au prochain point commode dans la boucle de traitement principale, reviendrait et relirait le fichier de configuration.

Ce qui fonctionne dépend en partie de ce que votre démon doit faire. S'il passe du temps dans une conversation avec ses clients, vous pouvez ne pas vouloir utiliser l'une des options 1 ou 2 - vous préférez utiliser l'option 3. Si vous faites des réponses uniques à des questions simples, les approches brutales peuvent être efficace (et sont probablement plus simples à programmer). Notez que l'option 1 nécessite une manipulation soigneuse du WIP (travail en cours) et des choses comme les fichiers ouverts - si vous ne faites pas attention, vous perdrez la trace des ressources, et le démon échouera (mémoire insuffisante, descripteurs de fichier - probablement l'un de ces deux).

0

Dépend de la façon dont vous le structurez; Si vous manipulez plusieurs connexions dans un seul thread/processus, alors vous devriez probablement les avertir en quelque sorte de quitter (si vous le pouvez, cela dépend du protocole) avant de recharger le fichier config (ou exec lui-même). Si le protocole vous permet de dire «partez et revenez plus tard», il est clair que c'est une bonne victoire. Si les clients doivent rester connectés, vous pouvez appliquer les modifications de configuration aux clients déjà connectés, s'il s'agit d'un démon single-process-single-thread, si cela a du sens.

S'il s'agit d'un processus multiple, les choses deviennent plus complexes. Vous devez informer les processus de la nouvelle configuration, ou s'assurer qu'ils continuent avec l'ancienne configuration, ou qu'ils peuvent choisir la nouvelle configuration lorsque leur client se ferme. S'il s'agit d'un multi-thread, les threads doivent pouvoir lire en toute sécurité la nouvelle configuration au milieu de ce qu'ils sont en train de faire, ce qui peut nécessiter un verrouillage, ou vous pouvez allouer de la mémoire pour une nouvelle structure de configuration. un switch-over en quelque sorte,

1

J'ai trouvé cette page car je cherchais moi-même un exemple pour m'assurer que je le fais correctement. Comme il n'y a pas d'exemple pour cela, je vais poster ma tentative et de laisser d'autres commentaires à ce sujet:

volatile sig_atomic_t g_eflag = 0; 
volatile sig_atomic_t g_hupflag = 1; 

static void signal_handler(int sig) 
{ 
    switch(sig) 
    { 
    case SIGHUP: 
     g_hupflag = 1; 
     break; 
    case SIGINT: 
    case SIGTERM: 
     g_eflag = 1; 
     break; 
    } 
} 

int main(int argc, char **argv) 
{ 
    signal(SIGINT, signal_handler); 
    signal(SIGTERM, signal_handler); 
    signal(SIGHUP, signal_handler); 
    signal(SIGPIPE, SIG_IGN); 

    while(!g_eflag) 
    { 
     if(g_hupflag) 
     { 
      g_hupflag = 0; 
      load_config(); 
     } 

     // ... do daemon work ... 
    } 

    return 0; 
} 
Questions connexes