[C/Posix] Renvoi en tâche de fond

Le
JKB
Bonjour à tous,

Je suis en train de transformer un programme non interactif (mais
tournant dans un terminal) en daemon. Pour l'instant, je lance le truc
par un 'nohup mon_programme &', mais ce n'est pas satisfaisant pour
plusieurs raisons que je n'évoquerai pas ici (il y a au moins un
problème de redirection des flux parce que le truc utilise stderr et
stdout, des fflush() et nohup n'aime vraiment pas).

J'aimerais pouvoir lancer directement le truc et qu'il passe en
tâche de fond. J'ai commencé par rajouter un bout de code rendant le
programme insensible au signal SIGHUP. Je n'ai par contre rien trouvé
pour détacher le programme comme le fait '&' dans un shell. Je suppose
que ça doit être trivial, mais je ne dois pas chercher au bon endroit.

Merci de vos lumières,

JKB


--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Nicolas George
Le #18134691
JKB wrote in message
Pour l'instant, je lance le truc
par un 'nohup mon_programme &',



nohup est une connerie. L'opération correcte pour détacher un processus de
son terminal est setsid, mais ce n'est hélas pas une commande standard.
L'appel système est standard, et ici c'est ce qui t'intéresse.

Je n'ai par contre rien trouvé
pour détacher le programme comme le fait '&' dans un shell.



fork.
talon
Le #18134871
JKB
Bonjour à tous,

Je suis en train de transformer un programme non interactif (mais
tournant dans un terminal) en daemon. Pour l'instant, je lance le truc
par un 'nohup mon_programme &', mais ce n'est pas satisfaisant pour
plusieurs raisons que je n'évoquerai pas ici (il y a au moins un
problème de redirection des flux parce que le truc utilise stderr et
stdout, des fflush() et nohup n'aime vraiment pas...).

J'aimerais pouvoir lancer directement le truc et qu'il passe en
tâche de fond. J'ai commencé par rajouter un bout de code rendant le
programme insensible au signal SIGHUP. Je n'ai par contre rien trouvé
pour détacher le programme comme le fait '&' dans un shell. Je suppose
que ça doit être trivial, mais je ne dois pas chercher au bon endroit.

Merci de vos lumières,

JKB





Voici un exemple que j'avais fait en python, mais ça décalque ce qu'il
faut faire en C:

# Now become a daemon and make the socket accessible to the web browser
pid = os.fork()
if pid > 0 : sys.exit(0) # Exit original parent

# In first child become independant
os.chdir('/') # To not ober unmounts
os.umask(0)
os.setsid() # Become its own session leader

pid = os.fork()
if pid > 0 : # In first child
import time
time.sleep(3)
while not os.access(socket, os.F_OK) :
time.sleep(1)
# the socket created by the child is made accessible to the web
# server
os.chown(socket, wwwuid, wwwgid)
os.chmod(socket, 0700)
sys.exit(0) # Exit first child

# In second child close stdin, stdout, stderror
for i in range(3) : os.close(i)
# and redirect stdout, stderror to /dev/null
os.open('/dev/null', os.O_RDWR) # Becomes file descriptor 0
os.dup2(0,1)
os.dup2(0,2)




--

Michel TALON
JKB
Le #18135681
Le 14-12-2008, ? propos de
Re: [C/Posix] Renvoi en tâche de fond,
Nicolas George ?crivait dans fr.comp.os.unix :
JKB wrote in message
Pour l'instant, je lance le truc
par un 'nohup mon_programme &',



nohup est une connerie. L'opération correcte pour détacher un processus de
son terminal est setsid, mais ce n'est hélas pas une commande standard.
L'appel système est standard, et ici c'est ce qui t'intéresse.

Je n'ai par contre rien trouvé
pour détacher le programme comme le fait '&' dans un shell.



fork.



J'ai trouvé un truc qui demande _deux_ fork() et au passage un
setsid(), mais j'ai beau regarder, je ne vois pas pourquoi il faut
_deux_ fork(). Quid du signal SIGHUP ?

La séquence telle que je l'ai trouvée est donc :

fork() -> setsid() -> fork() sans traitement du SIGHUP...

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Stephane CHAZELAS
Le #18136061
2008-12-14, 12:28(+00), JKB:
[...]
J'ai trouvé un truc qui demande _deux_ fork() et au passage un
setsid(), mais j'ai beau regarder, je ne vois pas pourquoi il faut
_deux_ fork(). Quid du signal SIGHUP ?

La séquence telle que je l'ai trouvée est donc :

fork() -> setsid() -> fork() sans traitement du SIGHUP...


[...]

Il te faut un fork pour pouvoir faire un setsid() car tu ne peux
pas faire un setsid() si tu es deja un process group leader.
L'idee du deuxieme fork() est pour ne plus etre un session
leader. Le danger quand on est un session leader est que si on
ouvre un tty device sans le O_NOCTTY fcntl flag, on se retrouve
attaché a ce terminal et on a fait tout ca justement pour se
detacher d'un terminal.

Le SIGHUP est lancé quand le terminal hang up. Le but de la
manoeuvre est de se detacher du terminal, donc une fois qu'on a
fait ca, on ne recevra plus de SIGHUP pour cette raison, et on
peut d'ailleurs utilier ce signal pour autre chose. Typiquement,
il y a un certain nombre de daemon (typiquement syslog) qui
relisent leur conf sur reception de SIGHUP. Donc on n'a pas
besoin et meme on ne veut pas ignorer SIGHUP.

--
Stéphane
talon
Le #18137001
JKB
Le 14-12-2008, ? propos de
Re: [C/Posix] Renvoi en tâche de fond,
Nicolas George ?crivait dans fr.comp.os.unix :
> JKB wrote in message >> Pour l'instant, je lance le truc
>> par un 'nohup mon_programme &',
>
> nohup est une connerie. L'opération correcte pour détacher un processus de
> son terminal est setsid, mais ce n'est hélas pas une commande standard.
> L'appel système est standard, et ici c'est ce qui t'intéresse.
>
>> Je n'ai par contre rien trouvé
>> pour détacher le programme comme le fait '&' dans un shell.
>
> fork.

J'ai trouvé un truc qui demande _deux_ fork() et au passage un
setsid(), mais j'ai beau regarder, je ne vois pas pourquoi il faut
_deux_ fork(). Quid du signal SIGHUP ?



Le premier père peut exiter et retourner le contrôle du terminalà
l'utilisateur. Son fils n'a plus de parent et c'est init qui supprimera
le zombie. Le fils devient leader de session et donc ne va plus recevoir
les signaux délivrés à la session du père. Avec le deuxième fork, le
petit fils n'est pas leader de session et n'a pas de terminal de
contrôle. Les IO standards sont aussi fermés.


--

Michel TALON
JKB
Le #18142611
Le 14-12-2008, ? propos de
Re: [C/Posix] Renvoi en tâche de fond,
Stephane CHAZELAS ?crivait dans fr.comp.os.unix :
2008-12-14, 12:28(+00), JKB:
[...]
J'ai trouvé un truc qui demande _deux_ fork() et au passage un
setsid(), mais j'ai beau regarder, je ne vois pas pourquoi il faut
_deux_ fork(). Quid du signal SIGHUP ?

La séquence telle que je l'ai trouvée est donc :

fork() -> setsid() -> fork() sans traitement du SIGHUP...


[...]

Il te faut un fork pour pouvoir faire un setsid() car tu ne peux
pas faire un setsid() si tu es deja un process group leader.
L'idee du deuxieme fork() est pour ne plus etre un session
leader. Le danger quand on est un session leader est que si on
ouvre un tty device sans le O_NOCTTY fcntl flag, on se retrouve
attaché a ce terminal et on a fait tout ca justement pour se
detacher d'un terminal.

Le SIGHUP est lancé quand le terminal hang up. Le but de la
manoeuvre est de se detacher du terminal, donc une fois qu'on a
fait ca, on ne recevra plus de SIGHUP pour cette raison, et on
peut d'ailleurs utilier ce signal pour autre chose. Typiquement,
il y a un certain nombre de daemon (typiquement syslog) qui
relisent leur conf sur reception de SIGHUP. Donc on n'a pas
besoin et meme on ne veut pas ignorer SIGHUP.



Merci pour ces informations, je vais tester de ce pas.

Cordialement,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Damien Wyart
Le #18143401
* JKB
J'aimerais pouvoir lancer directement le truc et qu'il passe en tâche
de fond. J'ai commencé par rajouter un bout de code rendant le
programme insensible au signal SIGHUP. Je n'ai par contre rien trouvé
pour détacher le programme comme le fait '&' dans un shell. Je suppose
que ça doit être trivial, mais je ne dois pas chercher au bon endroit.



Quelques petites docs en ligne sur le sujet :
http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
http://www.enderunix.org/docs/eng/daemon.php

Sinon, tu as cette petite bibliothèque qui est assez pratique :
http://0pointer.de/lennart/projects/libdaemon/


--
DW
JKB
Le #18143941
Le 15-12-2008, ? propos de
Re: [C/Posix] Renvoi en tâche de fond,
Damien Wyart ?crivait dans fr.comp.os.unix :
* JKB
J'aimerais pouvoir lancer directement le truc et qu'il passe en tâche
de fond. J'ai commencé par rajouter un bout de code rendant le
programme insensible au signal SIGHUP. Je n'ai par contre rien trouvé
pour détacher le programme comme le fait '&' dans un shell. Je suppose
que ça doit être trivial, mais je ne dois pas chercher au bon endroit.



Quelques petites docs en ligne sur le sujet :
http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize
http://www.enderunix.org/docs/eng/daemon.php



Le premier me semble bien.

Sinon, tu as cette petite bibliothèque qui est assez pratique :
http://0pointer.de/lennart/projects/libdaemon/



Ça ne va pas être possible au regard de la portabilité demandée...

Merci,

JKB

--
Le cerveau, c'est un véritable scandale écologique. Il représente 2% de notre
masse corporelle, mais disperse à lui seul 25% de l'énergie que nous
consommons tous les jours.
Che Averell
Le #18143931
Damien Wyart
Quelques petites docs en ligne sur le sujet :
http://www-theorie.physik.unizh.ch/~dpotter/howto/daemonize



Juste une question en passant. Cette page indique de faire ceci :
freopen( "/dev/null", "r", stdin);
freopen( "/dev/null", "w", stdout);
freopen( "/dev/null", "w", stderr);
Pourquoi ne pas tout simplement fermer stdin, stdout et stderr ? Bien
entendu, dans le cas où l'appli n'écrit plus jamais dans stdout et
stderr, ce qui pour un daemon me semble quand même être le minimum...
Damien Wyart
Le #18144081
* Che Averell
Juste une question en passant. Cette page indique de faire ceci :
freopen( "/dev/null", "r", stdin);
freopen( "/dev/null", "w", stdout);
freopen( "/dev/null", "w", stderr);
Pourquoi ne pas tout simplement fermer stdin, stdout et stderr ? Bien
entendu, dans le cas où l'appli n'écrit plus jamais dans stdout et
stderr, ce qui pour un daemon me semble quand même être le minimum...



Selon les sources, l'une ou l'autre stratégie sera préférée, et les deux
sont souvent citées dans les docs. Je pense que c'est une question de
goût et d'habitude, sachant que si l'on convertit un programme complexe
en daemon, il peut rester des appels aux E/S standards non supprimés et
que c'est plus propre de les envoyer sur /dev/null que de les fermer
complètement.

--
DW
Publicité
Poster une réponse
Anonyme