Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

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

12 réponses
Avatar
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.

10 réponses

1 2
Avatar
Nicolas George
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.
Avatar
talon
JKB wrote:
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
Avatar
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 ?

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.
Avatar
Stephane CHAZELAS
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
Avatar
talon
JKB wrote:
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
Avatar
JKB
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.
Avatar
Damien Wyart
* JKB in fr.comp.os.unix:
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
Avatar
JKB
Le 15-12-2008, ? propos de
Re: [C/Posix] Renvoi en tâche de fond,
Damien Wyart ?crivait dans fr.comp.os.unix :
* JKB in fr.comp.os.unix:
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.
Avatar
Che Averell
Damien Wyart écrit :
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...
Avatar
Damien Wyart
* Che Averell in fr.comp.os.unix:
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
1 2