CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C]prog système,relancement auto service

sd460
sd460
Niveau 10
16 novembre 2010 à 16:05:56

Bonjour,

Je fais suite à un topic sur le forum Linux ( https://www.jeuxvideo.com/forums/1-38-7705220-1-0-1-0-relancement-automatique-service.htm )

Je cherche à coder un programme en C qui permette de lancer un service, et qui soit en charge de relancer ce même service en cas de plantage par seg fault.

Sur le précédent topic, on m'a conseillé d'utiliser wait() pour gérer ca.

Pour l'instant j'ai ca :

void main(void)
{
int sts;
int val;

sts=fork();
if (sts == 0) {
val = execve("/usr/sbin/myService",NULL,NULL);
printf("value returned : %d\n",val);
}
wait(&sts);
printf("IOP\n");
}

d'après le man :
"execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded.
"

Du coup si cela ne retourne rien, cela veut dire que c'est bloquant ? C'est ce que je croyais, mais en fait non apparemment.
du coup dans mon programme (enfin, le début...) , le service est bien lancé, mais le programme se termine sans que je puisse monitorer le service, ce qui est gênant.

Je ne comprends pas sur quoi doit porter une boucle dans le main...

Merci

godrik
godrik
Niveau 30
16 novembre 2010 à 16:58:21

exec ce n'est pas comme ca que ca marche.
quand tu fais exec, le system desalloue toute la memoire, decharge le code du programme, charge le code du programme que tu veux lancer et appel main().
exec REMPLACE le processus courant par le programme que tu cherche a lancer. Donc l'appel a exec ne retourne jamais. SAUF si l'appel a exec echoue.

sd460
sd460
Niveau 10
16 novembre 2010 à 17:28:27

ah, c'est effectivement la partie du man que je n'étais pas sur d'avoir compris :honte:

Je suis obligé d'utiliser exec n'est-ce pas ? Ou y-a-t-il une alternative :question:

godrik
godrik
Niveau 30
16 novembre 2010 à 18:01:14

il faut utiliser exec
typiquement ce que tu fais est:
begin:
fork()
if (jesuislefils)
{
exec(...)
}
else
{
//je suis le pere
if (!systemshutdown)
goto begin;
}

sd460
sd460
Niveau 10
17 novembre 2010 à 16:30:44

ok je vois.
Mais, comment est-ce que je peux traiter cette condition : "if (!systemshutdown) " :question:
Si je récupère le pid du service, je peux utiliser un waitpid à la limite , non :question:
Par contre, cela demande de récupérer le pid du service, ce que je ne peux faire qu'après le lancement du service donc après le "exec". Or je perds la main une fois que le exec est exécuté....

godrik
godrik
Niveau 30
17 novembre 2010 à 17:21:39

ce que je veux dire par systemshutdown, c'est que tu peux vouloir explicitement ne pas relance le programme.
c'est pour ca que tu fork avant. C'est le pere qui fait ca. pas le fils.

sd460
sd460
Niveau 10
17 novembre 2010 à 17:27:51

ah oui effectivement, j'avais mal interprété...
Mais après le exec, je perds le fils (dans le sens je ne maîtrise plus son exécution) non ?
Donc c'est bel et bien dans le père que je dois gérer le relancement non ?
et le seul moyen serait avec un waitpid ?

godrik
godrik
Niveau 30
17 novembre 2010 à 17:33:56

apres exec, le fils devient le service que tu cherches a relancer.

Tu peux utiliser waitpid pour savoir quand le service se termine.
Tu dois meme pouvoir obtenir le code de retour du service et determiner si il s'est terminer parceque c'est fini ou parcequ'il a crasher.

sd460
sd460
Niveau 10
17 novembre 2010 à 19:01:33

Voila ce que j'ai fait : http://pastebin.com/giBGSaTB

Il se trouve que j'ai un problème avec waitpid, car il ne bloque pas dans mon programme (il semble que waitpid retourne tout de suite quelquechose alors que mon service tourne avec le pid que j'ai récupéré avant.)

Voici la sortie du programme ci après.
Ca boucle alors que cela ne devrait pas il me semble...et donc évidemment quand le exec se lance une deuxième fois, cela renvoit une erreur.

$ sudo ./mergesort
PID:12139 IOPIOP
myService already running on /var/run/myService/myService.ctl.
PID:12139 IOPIOP
myService already running on /var/run/myService/myService.ctl.
PID:12139 IOPIOP
myService already running on /var/run/myService/myService.ctl.
PID:12139 IOPIOP
myService already running on /var/run/myService/myService.ctl.

godrik
godrik
Niveau 30
17 novembre 2010 à 19:28:21

C'est quoi ce service si c'est pas indiscret ?

Puet etre que le programme que tu lance n'est en fait qu'un wrapper qui lance le vrai process. Du coup, tu detecte la mort du wrapper...

Dans ce cas, tu peuyx vouloir attendre de ne plus avoir de fils du tout. regarde le code de retour de wait et le errno ECHILD dans le manuel.

sd460
sd460
Niveau 10
17 novembre 2010 à 20:37:36

c'est pas indiscret, il s'agit d'asteriks.
Le code de retour de wait est -1 ce qui est plutot mauvais signe^^

PID:21677
PID:21677 - ECHILD:10 - i:-1

le ps donne ca à des moments différents pendant que la boucle tourne : http://pastebin.com/RywqHLUx

Du coup :question:

dnob700
dnob700
Niveau 10
18 novembre 2010 à 00:11:55

ton appel à waitpid ne vas pas du tout. le premier argument doit être le pid du processus à attendre (donc ta variable sts et non pas une variable pid que tu initialise à 0) puis le second argument est une variable qui recevra le statut du processus lorsqu'il va être mort.

Par ailleurs, je n'arrive pas à le retrouver mais je crois qu'il existe un utilitaire système assez standard pour faire ce genre de chose que tu pourrais vouloir utiliser.

godrik
godrik
Niveau 30
18 novembre 2010 à 00:18:26

dnob, je ne connais que start-stop-daemon. et ca ne relance pas automatiquement sur un crash.
Cependant, maintenant que tu le mentionnes, ca m'etonne que ca n'existe pas.

sd460
sd460
Niveau 10
18 novembre 2010 à 00:35:07

dnob :d) pid est modifié dans le scanf deux lignes au dessus de waitpid.

Si vous avez le nom d'un tel utilitaire, je prends bien sur, mais j'aimerai également savoir pourquoi cela ne fonctionne pas dans mon programme...

jesus_le_criss
jesus_le_criss
Niveau 7
18 novembre 2010 à 02:55:03

on peut utiliser des goto en C ? :D

godrik
godrik
Niveau 30
18 novembre 2010 à 04:08:03

bien sur qu'on peut utiliser des goto en C... C'est assez utile pour la gestion d'erreur d'ailleurs. Bien que dans ce cas la, une boucle est plus approprie.

sd460
sd460
Niveau 10
18 novembre 2010 à 16:34:39

on m'a toujours dit qu'utiliser un goto était une espèce d'abomination en C, je ne sais pas trop pourquoi, je trouve ca assez propre dans certains cas, mais du coup je ne les utilise pas. Cela dit, j'ai pas fait beaucoup de C.

Bon, je ne comprends toujours pas.
Je lance mon programme
- il lance le service
- le waitpid retourne une erreur
- ca boucle avec 2 erreurs : lancement du service impossible (normal car il a déjà été lancé une fois) + erreur du waitpid.

Si je laisse tourner ce programme, en parallèle je peux me connecter à la console du service, qui fonctionne. Si je fais un kill -9 sur le pid indiqué par mon programme, ca tue bien mon service.... Donc je ne comprends rien :-)

dnob700
dnob700
Niveau 10
18 novembre 2010 à 22:35:05

si waitpid renvoie une erreur (i.e. -1) regarde quelle est l'erreur. la variable errno (qui est défini dans errno.h) prend une certaines valeur que tu peux passer aux fonction strerror et Cie pour avoir un message d'erreur explicatif sur ton problème. Regardes le et si ça ne te suffit pas, donne le nous, ça nous aidera à comprendre ce qui ne vas pas.

Celà dit, dans le processus père, fork renvoie le pid du processus fils. Est-ce qu'il correspond avec le pid que tu récupère par ton fscanf (que, honnêtement, je ne comprend pas).

dnob700
dnob700
Niveau 10
18 novembre 2010 à 22:38:44

parce que, avec waitpid, je ne suis pas sûr du tout que tu as le droit d'attendre un processus dont tu n'es pas le père, y compris si son père à lui est mort entre temps (pareil avec wait, contrairement à ce qu'a écrit godrik plus haut, si je ne me trompe pas trop).

godrik
godrik
Niveau 30
18 novembre 2010 à 22:53:46

dans ma memoire de mes cours de systeme. Il me semble que quand le pere d'un processus meurt, , le grand pere devient le pere. Mais ca pourrait ne pas etre standard, ou etre completemenet faux.

Sous forums
  • Aide à l'achat Mac
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Steam Deck
  • Macintosh
  • Hardware
La vidéo du moment